Lazy Cartesian Produkt von Arrays (beliebige verschachtelte Schleifen)

8

Es gibt andere Fragen zu diesem in andere Sprachen und andere nicht-faul JavaScript Versionen , aber keine faulen JavaScript-Versionen, die ich gefunden habe.

Gegeben ein Array mit einer beliebigen Anzahl von Arrays beliebiger Größe:

%Vor%

und eine Rückruffunktion:

%Vor%

Was ist eine elegante Methode, um den gesamten Produktraum zu durchlaufen, ohne zuerst eine große Auswahl aller möglichen Kombinationen zu erstellen?

%Vor%

Beachten Sie, dass diese Kombinationen mit den Ergebnissen übereinstimmen, die Sie erhalten würden, wenn Sie geschachtelte Schleifen hätten:

%Vor%

Die Vorteile des kartesischen Produkts sind:

  1. Sie können eine beliebige Anzahl von Schleifen verschachteln (vielleicht wissen Sie nicht, wie viele Elemente Sie durchlaufen)
  2. Sie können die Reihenfolge der Schleifen ändern (z. B. zuerst die Schleife nach Adjektiven), ohne Ihren Code bearbeiten oder alle möglichen Kombinationen der Schleifenreihenfolge ausgeben zu müssen.

Benchmarks

Sie können die Benchmarks für die Antworten hier unten sehen:
Ссылка

    
Phrogz 23.02.2012, 22:27
quelle

4 Antworten

5

Zufälligerweise arbeiten wir am Wochenende an derselben Sache. Ich habe versucht, alternative Implementierungen zu meinem [].every -basierten Algo zu finden, die in Firefox eine abartige Leistung zeigten (aber in Chrome schreit - mehr als doppelt so schnell wie die nächste).

Das Endergebnis ist Ссылка . Es ist ähnlich zu Tomalaks Ansatz, aber es gibt nur ein Argumenten-Array, das mutiert wird, wenn sich die Carets bewegen, anstatt jedes Mal generiert zu werden.

Ich bin mir sicher, dass es weiter verbessert werden könnte, wenn man die clevere Mathematik in den anderen Algos benutzt. Ich verstehe sie jedoch nicht ganz, also überlasse ich es anderen, es zu versuchen.

EDIT: der eigentliche Code, dieselbe Schnittstelle wie Tomalaks. Ich mag diese Schnittstelle, weil sie jederzeit geändert werden kann. Es ist nur etwas langsamer als wenn die Schleife in der Funktion selbst inline ist.

%Vor% %Vor%     
monzee 27.02.2012, 00:40
quelle
7

Eine Kombination aus Rekursion und Iteration wird den Job erledigen.

%Vor%

Demo: Ссылка

%Vor%     
Rob W 23.02.2012 22:46
quelle
5

Ich habe diese Lösung erstellt:

%Vor%

Es wird so benutzt:

%Vor%

Es scheint gut zu funktionieren, aber es ist nicht sehr gründlich getestet, sagen Sie mir, wenn Sie Fehler finden.

Vergleiche: Ссылка

    
Tomalak 24.02.2012 00:56
quelle
5

Hier ist meine Lösung, Rekursion verwendend. Ich mag es nicht, dass beim ersten Durchlauf ein leeres Array erstellt wird oder dass if in der for -Schleife verwendet wird (anstatt den Test in zwei Schleifen für die Geschwindigkeit abzuwickeln, auf Kosten von DRYness) ) aber zumindest ist es eine Art knappe:

%Vor%

Gesehen in Aktion: Ссылка

Bearbeiten : Hier ist eine viel schnellere Version, ungefähr 2x-10x schneller als das oben genannte:

%Vor%

Anstatt benutzerdefinierte Arrays für jeden rekursiven Aufruf zu erstellen, wird ein einzelnes Array ( p ) für alle Parameter erneut verwendet. Sie können auch ein Kontextargument für die Funktion application übergeben.

Bearbeiten 2 : Wenn Sie einen wahlfreien Zugriff auf Ihr kartesisches Produkt benötigen, einschließlich der Möglichkeit, eine Iteration in umgekehrter Reihenfolge durchzuführen, können Sie Folgendes verwenden:

%Vor%

Das obige Dekodieren der n Kombination für das kartesische Produkt von Arrays [a,b,...,x,y,z] lautet:

%Vor%

Sie können eine schöne Version der obigen Formel auf meiner Website sehen.

Die Dividenden und Moduli können durch Iteration der Mengen in umgekehrter Reihenfolge vorberechnet werden:

%Vor%

Damit ist das Nachschlagen einer bestimmten Kombination eine einfache Angelegenheit der Abbildung der Mengen:

%Vor%

Für reine Geschwindigkeits- und Vorwärtsiteration siehe jedoch die akzeptierte Antwort. Die obige Technik - selbst wenn wir die Liste der Dividenden und Module einmal vorberechnen - ist 2-4 mal langsamer als diese Antwort.

    
Phrogz 23.02.2012 22:34
quelle

Tags und Links