it-swarm.com.de

Wie verwandle ich eine Kartenliste in immutable.js in eine Karte von Karten?

Angenommen, ich habe eine immutable.js List wie folgt:

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

Ich möchte das in eine Map umwandeln, die so aussieht:

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

Wie verwandle ich xs in ys idiomatisch in immutable.js?

Mit idiomatisch meine ich, dass alle Zwischenstrukturen unveränderlich sein sollten. Ich denke, dass alle Zwischenschritte iterable Komposition verwenden würden, anstatt Zwischenbilder in voller Größe zu erzeugen.

Edit: Ich habe einen jsperf-Benchmark erstellt und vergleicht die bisherigen Antworten. Beide nicht-mutierenden Lösungen sind für mich ziemlich idiomatisch; Ich halte die Stimmen vielleicht durch und überlasse die Entscheidung, oder wir können durchhalten, bis wir eine Sammlung von ungefähr gleichermaßen idiomatischen Techniken zusammenstellen können.

23
CJ Gaconnet

Sie können die Eingabeliste in neue Immutable.Map reduzieren:

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

In diesem Fall gibt es keine Zwischendarstellung, aber die unveränderliche Karte muss in jeder Iteration aktualisiert werden (tatsächlich muss eine neue Instanz erstellt werden), und das kann suboptimal sein (abhängig von der tatsächlichen Implementierung von Immutable.Map).

Sie können es optimieren, indem Sie es in ein normales Javascript-Objekt reduzieren, und es am Ende in eine unveränderliche Karte konvertieren:

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

Das ist aber sicherlich weniger idiomatisch.

21
dkl

Eine Lösung kann die Verwendung des Map-Konstruktors von List sein:

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

Scheint so, aber ich bin mir nicht sicher, ob es sich um Zwischendarstellungen handelt

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

PS Es ist seltsam, aber ich kann nur .toKeyedSeq verwenden, nicht .toKeyedIterable, was eher geeignet ist.

2
mbeloshitsky

Sie können eine Liste von Karten gegen eine Liste von Listen austauschen, indem Sie reduce in Kombination mit mergeWith verwenden.

Reduzieren Sie die Sammlung und fügen Sie jedes neue Element zusammen, indem Sie seine Werte miteinander verketten. 

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