Lass A
und B
sei zwei Sätze. Ich suche nach sehr schnellen oder eleganten Methoden, um den eingestellten Unterschied ( A - B
oder A \B
, je nach Ihren Vorlieben) zwischen ihnen zu berechnen . Die beiden Sätze werden wie im Titel als Javascript-Arrays gespeichert und bearbeitet.
Anmerkungen:
- Gecko-spezifische Tricks sind in Ordnung
- Ich würde mich lieber an native Funktionen halten (aber ich bin offen für eine leichtgewichtige Bibliothek, wenn sie viel schneller ist)
- Ich habe JS.Set gesehen, aber nicht getestet (siehe vorherigen Punkt).
Bearbeiten: Ich habe einen Kommentar zu Sets mit doppelten Elementen bemerkt. Wenn ich "set" sage, beziehe ich mich auf die mathematische Definition, was (unter anderem) bedeutet, dass sie keine doppelten Elemente enthalten.
javascript
arrays
set-difference
Matt Ball
quelle
quelle
indexOf
Implementierung stecken bleiben .Antworten:
Wenn Sie nicht wissen, ob dies am effektivsten ist, aber vielleicht am kürzesten
Auf ES6 aktualisiert:
quelle
!B.includes(x)
anstelle vonB.indexOf(x) < 0
:)Nun, 7 Jahre später ist es mit dem Set- Objekt von ES6 recht einfach (aber immer noch nicht so kompakt wie das von Python
A - B
) und angeblich schneller alsindexOf
bei großen Arrays:quelle
Sie können ein Objekt als Karte verwenden, um ein lineares Scannen
B
für jedes Element vonA
wie in der Antwort von user187291 zu vermeiden :Die nicht standardmäßige
toSource()
Methode wird verwendet, um eindeutige Eigenschaftsnamen abzurufen. Wenn alle Elemente bereits eindeutige Zeichenfolgendarstellungen haben (wie dies bei Zahlen der Fall ist), können Sie den Code beschleunigen, indem Sie dietoSource()
Aufrufe löschen.quelle
Die kürzeste Verwendung von jQuery ist:
quelle
not
funktioniert ab 3.0.0-rc1 nicht mehr mit generischen Objekten. Siehe github.com/jquery/jquery/issues/3147Ich würde das Array B hashen und dann Werte aus dem Array A behalten, die in B nicht vorhanden sind:
quelle
getDifference(a, b, hashOfB)
folgt : Wenn es nicht bestanden wird, wird es berechnet, andernfalls wird es unverändert wiederverwendet.Wenn
each
wir die Idee von Christoph einbeziehen und einige nicht standardmäßige Iterationsmethoden für Arrays und Objekte / Hashes ( und Freunde) annehmen , können wir Differenz, Vereinigung und Schnittmenge in linearer Zeit in insgesamt etwa 20 Zeilen festlegen:Dies setzt voraus, dass
each
undfilter
für Arrays definiert sind und dass wir zwei Dienstprogrammmethoden haben:myUtils.keys(hash)
: Gibt ein Array mit den Schlüsseln des Hash zurückmyUtils.select(hash, fnSelector, fnEvaluator)
: Gibt ein Array mit den Ergebnissen des AufrufsfnEvaluator
der Schlüssel / Wert-Paare zurück, für diefnSelector
true zurückgegeben wird.Das
select()
ist lose von Common Lisp inspiriert und ist nurfilter()
undmap()
in einem gerollt. (Es wäre besser, sie definiert zu habenObject.prototype
, aber dies führt zu einem Chaos mit jQuery, sodass ich mich für statische Dienstprogrammmethoden entschieden habe.)Leistung: Testen mit
gibt zwei Sätze mit 50.000 und 66.666 Elementen. Mit diesen Werten dauert AB ungefähr 75 ms, während Vereinigung und Schnittpunkt jeweils ungefähr 150 ms betragen. (Mac Safari 4.0 mit Javascript-Datum für das Timing.)
Ich denke, das ist eine anständige Auszahlung für 20 Codezeilen.
quelle
hasOwnProperty()
, ob die Elemente numerisch sind. Andernfalls kann in der Ergebnismenge niemals so etwas wieObject.prototype[42] = true;
Mittel42
auftretenVerwenden von Underscore.js (Bibliothek für funktionales JS)
quelle
Einige einfache Funktionen, die aus der Antwort von @ milan stammen:
Verwendung:
quelle
Der fastete Weg ist nicht so elegant, aber ich habe einige Tests durchgeführt, um sicherzugehen. Das Laden eines Arrays als Objekt ist in großen Mengen viel schneller zu verarbeiten:
Ergebnisse:
Dies funktioniert jedoch nur mit Zeichenfolgen . Wenn Sie nummerierte Sätze vergleichen möchten, möchten Sie die Ergebnisse mit parseFloat zuordnen .
quelle
b.filter(function(v) { return !A[v]; });
in der zweiten Funktion sein?Das funktioniert, aber ich denke, ein anderer ist viel kürzer und auch eleganter
quelle