2015-04-11 4 views
21

Supposons que j'ai un immutable.js List comme ceci:Comment transformer une liste de cartes en une carte de cartes dans immutable.js?

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

Je veux transformer cela en une carte qui ressemble à ceci:

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

Comment puis-je tourner xs en ys idiomatiques en immuable .js?

Par idiomatiquement Je veux dire que toutes les structures intermédiaires doivent être des structures immutable.js, et je pense que toutes les étapes intermédiaires utiliseraient iterable composition au lieu de créer des représentations intermédiaires en taille réelle.

Modifier: J'ai créé un jsperf benchmark en comparant les réponses fournies jusqu'à présent. Les deux solutions non-mutantes me semblent assez idiomatiques; Je peux tenir et laisser les votes décider de la réponse choisie ou tenir jusqu'à ce que nous puissions rassembler une collection de techniques à peu près idiomatiques.

+0

Voulez-vous vraiment une carte des cartes, ou voulez-vous une carte des objets? – Bergi

+1

@Bergi Carte des cartes - immuable tout le long. –

Répondre

2

On dirait, mais je ne suis pas sûr de représentations intermédiaires

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

PS Il est étrange, mais je suis ne peut utiliser .toKeyedSeq, non .toKeyedIterable, qui est plus approprié.

20

Vous pouvez réduire la liste d'entrée dans le nouveau Immutable.Map:

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

Il n'y a pas de représentation intermédiaire dans ce cas, mais la carte immuable doit être mis à jour (en fait, nouvelle instance doit être créée) dans chaque itération et que cela peut être sous-optimal (en fonction de la mise en œuvre réelle de Immutable.Map).

Vous pouvez l'optimiser en réduisant l'objet régulier javascript et de le convertir à la carte immuable à la fin:

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

Mais qui est certainement moins idiomatiques.

+0

Merci pour la réponse bien motivée! Je pense que c'est la meilleure réponse. Mais quand je compare la performance de la mise à jour de la carte à chaque itération et la construction d'une nouvelle à la fin, je vois toujours que la première est presque 10% plus rapide, ce qui est le contraire de ce que vous avez mentionné à la fin : https://jsperf.com/immutable-js-list-of-maps-to-map-of-maps/1 – theopak

18

Une solution peut être d'utiliser le constructeur Carte de la liste:

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

Ceci est la bonne réponse – astreltsov

0

Vous pouvez échanger une liste des cartes à une carte des listes en utilisant reduce combiné avec mergeWith.

Réduire à travers la collection et fusionner chaque nouvel élément en concaténant ses valeurs ensemble.

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