2015-04-11 18 views
21

Supponiamo che io sono un immutable.js List come questo:Come trasformare un elenco di mappe in una mappa di Maps in immutable.js?

var xs = Immutable.fromJS([{key: "k", text: "foo"}]) 

voglio trasformarla in una mappa che assomiglia a questo:

var ys = Immutable.fromJS({k: {key: "k", text: "foo"}}) 

Come faccio girare xs in ys idiomaticamente in immutabili js?

Con idiomaticamente intendo che eventuali strutture intermedie dovrebbero essere strutture immutable.js, e ritengo che passaggi intermedi userebbe iterable composition invece di creare rappresentazioni intermedie full-size.

Modifica: ho creato un jsperf benchmark confrontando le risposte fornite finora. Entrambe le soluzioni non mutanti mi sembrano abbastanza idiomatiche; Potrei resistere e lasciare che i voti decidano la risposta scelta o resistere fino a quando non possiamo raccogliere una raccolta di tecniche ugualmente idiomatiche.

+0

Vuoi veramente una mappa di Maps o vuoi una mappa di oggetti? – Bergi

+1

@Bergi Mappa di Maps - immutabile fino in fondo. –

risposta

2

sembra che questo, ma io non sono sicuro di rappresentazioni intermedie

ys = Immutable 
    .fromJS([{key:'k', value:'xxx'}]) 
    .toKeyedSeq() 
    .mapEntries(function (kv) { return [kv[1].get('key'), kv[1]]; }) 

PS E 'strano, ma io sono in grado di utilizzare solo .toKeyedSeq, non .toKeyedIterable, che è più appropriato.

20

È possibile ridurre la lista di input nella nuova Immutable.Map:

var ys = xs.reduce(
     function(result, item) { return result.set(item.get('key'), item); }, 
     Immutable.Map()); 

Non c'è rappresentazione intermedia in questo caso, ma la mappa immutabile deve essere aggiornata (in realtà, nuova istanza deve essere creata) in ogni iterazione e ciò che può essere subottimale (a seconda dell'implementazione effettiva di Immutable.Map).

è possibile ottimizzare la riduzione in regolare oggetto JavaScript e convertirlo alla mappa immutabile alla fine:

var ys = Immutable.Map(xs.reduce(
     function(result, item) { result[item.get('key')] = item; return result; }, 
     {})); 

ma che è certamente meno idiomatica.

+0

Grazie per la risposta ben motivata! Penso che questa sia la migliore risposta. Ma quando paragono le prestazioni dell'aggiornamento della Mappa ad ogni iterazione, rispetto alla costruzione di una nuova alla fine, sto costantemente vedendo che farlo il primo modo è quasi il 10% più veloce, che è l'opposto di quello che hai citato alla fine : https://jsperf.com/immutable-js-list-of-maps-to-map-of-maps/1 – theopak

18

Una soluzione potrebbe essere quella di utilizzare Mappa costruttore dal listino:

const ys = Immutable.Map(xs.map(v => [v.get('key'), v])); 
+1

Questa è la risposta corretta – astreltsov

0

È possibile scambiare un elenco di mappe ad una mappa delle liste da utilizzare in combinazione con reducemergeWith.

Ridurre attraverso la raccolta e unire ogni nuovo elemento concatenando i suoi valori insieme.

collection.reduce((rr, ii) => rr.mergeWith((aa, bb) => List().concat(aa, bb), ii)) 
Problemi correlati