Entonces, tengo una Lista a:
let a = Immutable.List([1])y Lista b:
let b = Immutable.List([2, 3]) Quiero obtener List union === List([1, 2, 3]) de ellos.
Intento fusionarlos puño:
let union = a.merge(b); // List([2, 3]) Parece que el método de merge opera con índices, no con valores, por lo que anula el primer elemento de la List a con el primer elemento de la List b . Entonces, mi pregunta es cuál es la forma más simple de unir varias listas (idealmente sin iterar sobre ellas y otras operaciones adicionales).
Tienes razón sobre fusionar. Combinar actualizará el índice con el valor actual de la lista de combinación. Así que en tu caso tuviste
[0] = 1y lo fusionó con
[0] = 2 [1] = 3 que terminó sobrescribiendo [0]=1 con [0]=2 , y luego estableció [1]=3 dando como resultado su matriz [2,3] observada después de la fusión.
Un enfoque muy simple para resolver esto sería usar concat
var a = Immutable.List([1]); var b = Immutable.List([2,3]); var c = a.concat(b);Y funcionará para esta situación. Sin embargo, si la situación es más compleja, esto puede ser incorrecto. Por ejemplo,
var a = Immutable.List([1,4]); var b = Immutable.List([2,3,4]);esto le daría dos 4 que técnicamente ya no es una unión. Desafortunadamente, no hay unión incluida en Immutable. Una manera fácil de implementarlo sería establecer cada valor en cada lista como la clave de un objeto y luego tomar esas claves como la unión resultante.
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); })); } Este proceso es O(2(n+m)) . Cualquier proceso que use contains o indexOf terminará siendo O(n^2) , por eso se usaron las claves aquí.
edición tardía
Hiper-rendimiento
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 realidad, Immutable.js tiene una unión: es para la estructura de datos Set:
https://facebook.github.io/immutable-js/docs/#/Set/union
Lo mejor de Immutable.js es que ayuda a introducir construcciones de programación más funcionales en JS; en este caso, una interfaz común y la capacidad de abstraer tipos de datos. Entonces, para llamar a union en sus listas, conviértalos en conjuntos, use union y luego vuelva a convertirlos en listas:
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.La implementación de List#merge ha cambiado desde que se publicó esta pregunta, y en la versión actual 4.0.0-rc-12 List#merge funciona como se esperaba y resuelve el problema.