webentwicklung-frage-antwort-db.com.de

Wie man die Vereinigung mehrerer unveränderlicher.js-Listen erhält

Also habe ich Liste a:

let a = Immutable.List([1])

und Liste b:

let b = Immutable.List([2, 3])

Ich möchte List union === List([1, 2, 3]) von ihnen erhalten.

Ich versuche zu verschmelzen sie Faust:

let union = a.merge(b); // List([2, 3])

Es sieht so aus, als würde die merge -Methode mit Indizes arbeiten, nicht mit Werten. Daher wird das erste Element von List a Mit dem ersten Element von List b Überschrieben. Meine Frage ist also, wie man am einfachsten mehrere Listen zusammenfasst (im Idealfall ohne sie und andere zusätzliche Operationen zu wiederholen).

34
Glen Swift

Sie haben Recht mit dem Zusammenführen. Merge aktualisiert den Index mit dem aktuellen Wert der Zusammenführungsliste. Also in deinem Fall hattest du

[0] = 1

und verschmolz es mit

[0] = 2
[1] = 3

dabei wurde [0]=1 mit [0]=2 überschrieben und dann [1]=3 eingestellt, was nach dem Zusammenführen zu Ihrem beobachteten [2,3] - Array führte.

Ein sehr einfacher Lösungsansatz wäre concat

var a = Immutable.List([1]);
var b = Immutable.List([2,3]); 

var c = a.concat(b);

Und es wird für diese Situation funktionieren. Wenn die Situation jedoch komplexer ist, kann dies falsch sein. Beispielsweise,

var a = Immutable.List([1,4]);
var b = Immutable.List([2,3,4]); 

dies würde dir zwei 4er geben, was technisch gesehen keine Gewerkschaft mehr ist. Leider ist in Immutable keine Gewerkschaft enthalten. Eine einfache Möglichkeit zur Implementierung besteht darin, jeden Wert in jeder Liste als Schlüssel für ein Objekt festzulegen und diese Schlüssel dann als resultierende Vereinigung zu übernehmen.

jsFiddle Demo

function union(left,right){
 //object to use for holding keys
 var union = {};

 //takes the first array and adds its values as keys to the union object
 left.forEach(function(x){
  union[x] = undefined;
 });

 //takes the second array and adds its values as keys to the union object
 right.forEach(function(x){
  union[x] = undefined;
 });

 //uses the keys of the union object in the constructor of List 
 //to return the same type we started with
 //parseInt is used in map to ensure the value type is retained
 //it would be string otherwise
 return Immutable.List(Object.keys(union).map(function(i){ 
  return parseInt(i,10); 
 }));
}

Dieser Prozess ist O(2(n+m)). Jeder Prozess, der contains oder indexOf verwendet, wird zu O(n^2), weshalb hier die Schlüssel verwendet wurden.

late edit

Hyper-Performant

function union(left,right){
    var list = [], screen = {};
    for(var i = 0; i < left.length; i++){
        if(!screen[left[i]])list.Push(i);
        screen[left[i]] = 1;
    }
    for(var i = 0; i < right.length; i++){
        if(!screen[right[i]])list.Push(i);
        screen[right[i]] = 1;
    }
    return Immutable.List(list);
}
26
Travis J

Eigentlich hat Immutable.js eine Union - es ist für die Set-Datenstruktur:

https://facebook.github.io/immutable-js/docs/#/Set/union

Das Tolle an Immutable.js ist, dass es dabei hilft, funktionalere Programmierkonstrukte in JS einzuführen - in diesem Fall eine gemeinsame Schnittstelle und die Möglichkeit, Datentypen zu abstrahieren. Um union auf Ihren Listen aufzurufen, konvertieren Sie sie in Mengen, verwenden union und konvertieren Sie sie dann zurück in Listen:

var a = Immutable.List([1, 4]);
var b = Immutable.List([2, 3, 4]); 
a.toSet().union(b.toSet()).toList(); //if you call toArray() or toJS() on this it will return [1, 4, 2, 3] which would be union and avoid the problem mentioned in Travis J's answer.
22

Die Implementierung von List#merge hat sich geändert, seitdem diese Frage gestellt wurde, und in der aktuellen Version 4.0.0-rc-12List#merge funktioniert wie erwartet und behebt das Problem.

1
darksmurf