web-dev-qa-db-fra.com

Comment transformer une liste de cartes en une carte de cartes dans immutable.js?

Supposons que j'ai un List immuable.js comme ceci:

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 transformer xs en ys idiomatiquement dans immutable.js?

Par idiomatiquement, je veux dire que toute structure intermédiaire devrait être une structure immuable.js, et je pense que toute étape intermédiaire utiliserait composition itérable au lieu de créer des représentations intermédiaires de taille normale.

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

23
CJ Gaconnet

Vous pouvez réduire la liste des entrées en un nouveau fichier 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 mise à jour (en fait, une nouvelle instance doit être créée) à chaque itération et cela peut être sous-optimal (selon l'implémentation réelle de Immutable.Map).

Vous pouvez l’optimiser en réduisant l’objet javascript normal et le convertir en carte immuable à la fin:

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

Mais c'est certainement moins idiomatique.

21
dkl

Une solution consiste peut-être à utiliser le constructeur Map de List:

const ys = Immutable.Map(xs.map(v => [v.get('key'), v]));
20
Julien Deniau

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

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

PS C'est étrange, mais je ne peux utiliser que .toKeyedSeq, pas .toKeyedIterable, ce qui est plus approprié.

2
mbeloshitsky

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

Réduisez la collection et fusionnez chaque nouvel élément en concaténant ses valeurs. 

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