Underscore: _.union funktioniert nicht mit Arrays von Objekten

Erstellt am 2. Okt. 2015  ·  32Kommentare  ·  Quelle: jashkenas/underscore

_.union erzeugt immer Duplikate, wenn Arrays von Objekten übergeben werden.

zB _.union( [ { a:1 } ], [ { a:1 } ]) gibt [ { a:1 }, { a:1 } ]

Perverserweise sagt Ihnen die isEqual-Funktion von underscore, dass die fraglichen Objekte gleich sind. Vielleicht könnten wir ein Flag / eine Option haben, die den zu verwendenden Gleichheitsvergleich vorschreibt, oder die Option, einen Komparator zu übergeben?

change

Hilfreichster Kommentar

Dieser Thread hat mich dazu inspiriert, _.intersectionWith , _.differenceWith , _.unionWith und _.uniqWith hinzuzufügen, um Vergleichsanpassungen in meinem eigenen Code vorzunehmen.

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

Alle 32 Kommentare

Ich bin überrascht, dass es die Vergleichsfunktion nicht bereits akzeptiert. :+1:

Es ist erwähnenswert, dass dies für alle anderen Array-Berechnungsfunktionen wie Differenz, Schnittmenge, Eindeutigkeit usw. gilt.

Es wäre schön, wenn die gesamte Palette von Array-Funktionen aktualisiert werden könnte, um die Verwendung eines anderen Gleichheitskomparators für Objekte zu ermöglichen.

Wäre es nicht einfacher, wenn wir eine Option hätten, die Gleichheit basierend auf einem booleschen Parameterwert vergleicht, der an die Funktion _.union() übergeben werden könnte? Wenn es wahr ist, werden automatisch alle Objekte in diesem Array verglichen.

ZB _.union([1, 2, 3, 10, [{a:1}, {a:1}]], true) , würde [1,2,3,10, {a:1}] ausgeben

@amiral84 Nein. Das hat nichts damit zu

@michaelficara Dann habe ich den Sinn dieses Themas übersehen? :D

@amiral84 Es scheint so. Der Feature Request wird im ersten Kommentar ausführlich und prägnant erklärt.

das zugrunde liegende Problem scheint in _.uniq da _.union lediglich eine Wrapper-Funktion für Unique und Flatten ist.

_.union = restArgs(function(arrays) {
  return _.uniq(flatten(arrays, true, true));
});

Dieser Thread hat mich dazu inspiriert, _.intersectionWith , _.differenceWith , _.unionWith und _.uniqWith hinzuzufügen, um Vergleichsanpassungen in meinem eigenen Code vorzunehmen.

var array = [ { 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }, { 'a': 1, 'b': 2 } ];

_.uniqWith(array, _.isEqual);
// => [{ 'a': 1, 'b': 2 }, { 'a': 1, 'b': 3 }]

oder etwas in der Art von _.isCollection um festzustellen, ob es sich um eine Sammlung handelt. Wenn es sich um eine Sammlung handelt, sollten die Vergleiche _.isEqual anstelle von === was bei einer Sammlung nicht gut ist.

@dperrymorrow

sollte _.isEqual anstelle von === was bei einer Sammlung nicht gut ist.

Dynamisches Schalten klingt nach einer schlechten Idee. JS verwendet === oder SameValueZero Vergleiche für viele Dinge. Wenn es notwendig ist, über diese Vergleiche hinauszugehen, würde etwas wie _.uniqWith ausreichen.

Danke dafür @jdalton , die von dir erwähnten _opWith -Funktionen sind absolut perfekt für das, was ich erreichen möchte. Hast du eine Idee, wann sie per Release verfügbar sein werden?

@jdalton guter Punkt zu den Vergleichen, aber würden Sie normalerweise nicht einen Schlüssel für eine Sammlung verwenden, anstatt Underscore zu zwingen, den gesamten Unterschied zwischen den Objekten zu erkennen?

Würde das Folgende nicht die Anfrage von @wilhen01 lösen _(wenn auch ausführlicher als gewünscht)_

_.chain([{ a: 1 }]).union( [{a: 1}]).unique('a').value();
//=> [{a: 1}]

Würde das Folgende nicht die Anfrage von @wilhen01 lösen (wenn auch ausführlicher als gewünscht)

_.uniq unterstützt das bereits.

richtig, das ist mein Punkt, der obige Code funktioniert derzeit wie gepostet.
Könnten Sie nicht einfach uniq / unique mit einem Schlüssel zum Ergebnis der Vereinigung aufrufen?

@dperrymorrow Denken Sie nur ein bisschen außerhalb dieses Beispiels und fügen Sie eine weitere Eigenschaft hinzu .

ok, gotcha, sorry ... Ich versuche nicht, streitlustig zu sein, wollte nur das Problem vollständig verstehen. Ich würde gerne eine Pull-Anfrage über die Funktion _.uniqWith senden.

Keine Sorge, das wäre krass.

_.intersectionWith, _.differenceWith, _.unionWith und _.uniqWith

Wäre es nicht eine schönere API, die Vergleichsfunktion nur optional als letztes Argument übergeben zu können, anstatt vier neue Funktionen zu prägen?

@jaschkenas

Wäre es nicht eine schönere API, die Vergleichsfunktion nur optional als letztes Argument übergeben zu können, anstatt vier neue Funktionen zu prägen?

Ja, es könnte getan werden, aber es gibt Komplikationen, da Methoden wie _.uniq bereits die Übergabe eines Iterierten unterstützen und auch stark mit Unterstützung für binäre / sortierte Suchflags und Kontextparameter überladen sind. Dies würde bedeuten, ein Arity-Sniffing einzuführen, das sich für diese Situation zu clever anfühlt. Dies würde auch zukünftige Modularisierungsbemühungen erschweren, da es viele optionale Funktionen an einem einzigen Punkt bündelt, wenn die Implementierungen vereinfacht und in separate Methoden aufgeteilt werden könnten.

Richtig, ein total bedauerliches Designproblem. Aber neue Funktionen zu entwickeln, nur um einen Komparator zu ermöglichen, fühlt sich auch nicht nach der richtigen Lösung an.

ok, also sind hier zusätzliche Vergleichsfunktionsparameter der richtige Weg?
Wenn ja, kann ich meine Pull-Anfrage aktualisieren.

Der einzige knifflige Teil, den ich sehe, besteht darin, das Parameter-Parsing etwas haariger zu machen, wie oben bei @jdalton erwähnt.

_.uniq = _.unique = function(array, isSorted, iteratee, context) {
  if (!_.isBoolean(isSorted)) {
    context = iteratee;
    iteratee = isSorted;
    isSorted = false;
  }
//...

Vielleicht fügen Sie eine zusätzliche Prüfung hinzu, um zu sehen, ob isSorted _.isFunction und behandeln Sie es dann als Komparator.

@jaschkenas

Aber neue Funktionen zu entwickeln, nur um einen Komparator zu ermöglichen, fühlt sich auch nicht nach der richtigen Lösung an.

Es kann die beste Option für eine schlechte Situation sein. Ich habe in letzter Zeit überladene Funktionen abgespalten und bin mit dem Ergebnis ziemlich zufrieden. Obwohl es die API-Oberfläche vergrößert, ermöglicht es einfachere Implementierungen und Gruppierungen ähnlicher Methoden wie maxBy , uniqBy , pickBy oder uniqWith , unionWith , zipWith oder sortedIndexBy , sortedIndexOf , sortedUniq . Im Fall von uniq nutze ich derzeit allerdings noch eine Shared-Base-Funktion.

haben diesen Pull-Request #2368 aktualisiert danke.

Ich bin :+1: für uniqBy oder uniqWith . Ich wäre absolut dagegen, uniq weiter zu überladen (wie derzeit #2368 vorgeschlagen wird)

:+1: @megawac , uniqBy .

Fwiw lodash wird uniqBy als aufgeteiltes Formular von _.uniq(array, iteratee) und _.uniqWith als Formular verwenden, um die Anpassung des Komparators zu ermöglichen.

Ja, auf den zweiten Gedanken ist uniqWith ein besserer Name

sollte ich dann mit der separaten Methode eine Anfrage auf Lodash ziehen?
Ich dachte, die beiden Projekte würden zusammengeführt, irre ich mich?

@dperrymorrow

sollte ich dann mit der separaten Methode eine Anfrage an Lodash ziehen?

Keine Notwendigkeit, sie sind bereits im Edge-Master-Zweig von Lodash.

Ich dachte, die beiden Projekte würden zusammengeführt, irre ich mich?

Noch nicht. Lodash v4 beweist jedoch einige der Ideen der Zusammenführung.

@jdalton Können Sie bitte etwas mehr über die Implementierung von _.uniqWith mit anderen Iterierten ausführen.

@Pavnii
Sicher. Sie können sich lodash/npm/_baseUniq ansehen .
Wenn ein comparator wird, verwendet es den arrayIncludesWith Helfer um die Prüfung statt arrayIncludes durchzuführen (Unterstrich ist contains ).

@jdalton Das hilft mir.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

danilopolani picture danilopolani  ·  5Kommentare

acl0056 picture acl0056  ·  5Kommentare

githublyp picture githublyp  ·  3Kommentare

jezen picture jezen  ·  8Kommentare

marcalj picture marcalj  ·  5Kommentare