web-dev-qa-db-fra.com

Comment obtenir l'union de plusieurs listes immutable.js

Donc, j'ai List a:

let a = Immutable.List([1])

et Liste b:

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

Je veux obtenir List union === List([1, 2, 3]) d'eux.

J'essaye de fusionner les poing:

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

Il semble que la méthode merge fonctionne avec des index, pas avec des valeurs, donc remplace le premier élément de List a Par le premier élément de List b. Donc, ma question est quel est le moyen le plus simple d'obtenir l'union de plusieurs listes (idéalement sans itérer sur elles et autres opérations supplémentaires).

34
Glen Swift

Vous avez raison sur la fusion. La fusion mettra à jour l'index avec la valeur actuelle de la liste de fusion. Donc, dans votre cas, vous aviez

[0] = 1

et l'a fusionné avec

[0] = 2
[1] = 3

qui a fini par écraser [0]=1 avec [0]=2, puis définir [1]=3, ce qui a pour résultat votre tableau [2,3] observé après la fusion.

Une approche très simple pour résoudre ce problème serait d'utiliser concat

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

var c = a.concat(b);

Et cela fonctionnera pour cette situation. Cependant, si la situation est plus complexe, cela peut être incorrect. Par exemple,

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

cela vous donnerait deux 4 qui ne sont plus techniquement une union. Malheureusement, aucun syndicat n'est inclus dans Immutable. Un moyen simple de l'implémenter serait de définir chaque valeur de chaque liste comme clé d'un objet, puis de prendre ces clés comme union résultante.

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); 
 }));
}

Ce processus est O(2(n+m)). Tout processus qui utilise contains ou indexOf va finir par être O(n^2) c'est pourquoi les clés ont été utilisées ici.

édition tardive

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

En fait, Immutable.js a une union - c'est pour la structure de données Set:

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

La grande chose à propos d'Immutable.js est qu'il aide à introduire des constructions de programmation plus fonctionnelles dans JS - dans ce cas, une interface commune et la possibilité d'abstraire des types de données. Donc, pour appeler union sur vos listes - convertissez-les en ensembles, utilisez union puis convertissez-les en listes:

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
Geoffrey Abdallah

L'implémentation de List#merge a changé depuis la publication de cette question et dans la version actuelle 4.0.0-rc-12List#merge fonctionne comme prévu et résout le problème.

1
darksmurf