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).
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.
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);
}
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.
L'implémentation de List#merge
a changé depuis la publication de cette question et dans la version actuelle 4.0.0-rc-12
List#merge
fonctionne comme prévu et résout le problème.