2015-05-08 10 views
26

Così, ho Elenco A:Come ottenere dall'unione di più immutable.js Elenca

let a = Immutable.List([1]) 

e Lista B:

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

voglio ottenere Lista union === List([1, 2, 3]) da loro.

cerco di merge loro pugno:

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

Sembra merge metodo funziona con gli indici, non con valori così la priorità prima voce di List a con prima voce di List b. Quindi, la mia domanda è qual è il modo più semplice per ottenere l'unione di più elenchi (idealmente senza iterare su di essi e altre operazioni extra).

+8

Stai cercando 'a.concat (b)'? – loganfsmyth

+1

@loganfsmyth God dammed, non notarlo nel doc) Grazie. puoi incollarlo come risposta in modo che io possa accettarlo. –

+0

Lmao, anche io non ho visto concat .. ho provato un sacco di cose .. grazie :) – Spock

risposta

20

Sei corretto per l'unione. Unisci aggiornerà l'indice con il valore corrente della lista di fusione. Quindi nel tuo caso hai avuto

[0] = 1 

e incorporato con

[0] = 2 
[1] = 3 

che ha finito per sovrascrivere [0]=1 con [0]=2, e quindi impostare [1]=3 conseguente vostro osservato [2,3] matrice dopo la fusione.

Un approccio molto semplice per risolvere questo sarebbe quello di utilizzare concat

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

var c = a.concat(b); 

E funzionerà per questa situazione. Tuttavia, se la situazione è più complessa, potrebbe essere errata. Ad esempio,

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

questo ti darebbe due 4 che non è tecnicamente più un sindacato. Sfortunatamente non c'è unione inclusa in Immutable. Un modo semplice per implementarlo sarebbe impostare ciascun valore in ogni elenco come chiave per un oggetto e quindi prendere quei tasti come unione risultante.

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

Questo processo è O(2(n+m)). Qualsiasi processo che usi contains o indexOf finirà per essere O(n^2) quindi è per questo che le chiavi sono state utilizzate qui.

ritardo modificare

Hyper-performante

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

Credo che questo possa essere un problema come approccio generale - quando i valori sono più complessi. Funzionerà per i valori che sono tipi immutabili - Map per esempio - perché il metodo 'toString()' del tipo è implementato - ma allora significa che ogni volta che si aggiunge il valore come una chiave dell'oggetto si finisce per chiamare 'toString() '- il che si traduce in un calo delle prestazioni. –

+0

@DoronZavelevsky - Non sono d'accordo, come approccio generale non c'è niente di sbagliato in questo. Nella tua micro-ottimizzazione specifica di essere preoccupato per l'utilizzo di toString, ho creato una versione speciale per evitare quel caso nel caso in cui altri fossero interessati. Puoi vederlo nella sezione * late edit *. –

20

realtà Immutable.js ha un sindacato - è per la struttura dei dati Set:

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

La cosa grandiosa di Immutable.js aiuta a introdurre più costrutti di programmazione funzionale in JS - in questo caso un'interfaccia comune e la capacità di astrarre i tipi di dati. Quindi, per chiamare union nelle tue liste - convertirle in serie, usare union e riconvertirle in liste:

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. 
+2

Grazie per aver risposto, ma suppongo che sia piuttosto anti-pattern quindi pattern. La conversione di diversi elenchi in insiemi e poi indietro sembra essere un sovraccarico rispetto all'utilizzo del metodo "concat" incorporato. –

+3

Mi piace come sia semplice questa risposta .. è stato sorpreso da come la risposta di Travis J è al confronto: http://jsperf.com/immutable-union/2 – ptim

+1

Sì, non si vorrebbe farlo spesso, e onestamente, se si utilizzano le operazioni di set, probabilmente ha senso utilizzare la struttura dati impostata. Detto questo, sono d'accordo, i costrutti di programmazione funzionale creano soluzioni molto eleganti e semplici - Sarei curioso di vedere le prestazioni di questa operazione simile usando mori.js oltre immutabile (dato che è una libreria più performante) –

Problemi correlati