Как преобразовать список карт в карту карт в immutable.js?
Предположим, что у меня есть immutable.js List
следующим образом:
var xs = Immutable.fromJS([{key: "k", text: "foo"}])
Я хочу преобразовать это в карту, которая выглядит так:
var ys = Immutable.fromJS({k: {key: "k", text: "foo"}})
Как превратить xs
в ys
идиоматически в immutable.js?
Идиоматически я подразумеваю, что любые промежуточные структуры должны быть неизменяемыми. js структурами, и я думаю, что любые промежуточные шаги будут использовать итеративную композицию вместо создания полноразмерного промежуточного представления.
Изменить: я создал тест jsperf, сравнивая предоставленные ответы. Оба не мутирующих решения чувствуют себя довольно идиоматично для меня; Я могу продержаться и позволить голосам решить выбранный ответ или продержаться, пока мы не сможем собрать сборник примерно одинаково идиоматических методов.
Ответы
Ответ 1
Вы можете уменьшить список входных данных в новый файл Immutable.Map:
var ys = xs.reduce(
function(result, item) { return result.set(item.get('key'), item); },
Immutable.Map());
В этом случае промежуточное представление отсутствует, но неизменяемая карта должна быть обновлена (фактически, новый экземпляр должен быть создан) на каждой итерации и что это может быть субоптимальным (в зависимости от фактической реализации Immutable.Map).
Вы можете оптимизировать его, сводя к регулярному объекту javascript и преобразовать его в неизменяемую карту в конце:
var ys = Immutable.Map(xs.reduce(
function(result, item) { result[item.get('key')] = item; return result; },
{}));
Но это, безусловно, менее идиоматично.
Ответ 2
Одним из решений может быть использование конструктора Map из списка:
const ys = Immutable.Map(xs.map(v => [v.get('key'), v]));
Ответ 3
Похоже на это, но я не уверен в промежуточных представлениях
ys = Immutable
.fromJS([{key:'k', value:'xxx'}])
.toKeyedSeq()
.mapEntries(function (kv) { return [kv[1].get('key'), kv[1]]; })
PS Это странно, но я могу использовать только .toKeyedSeq, а не .toKeyedIterable, что более уместно.
Ответ 4
Вы можете поменять список карт на карту списков с помощью reduce
в сочетании с mergeWith
.
Уменьшить объем сбора и объединить каждый новый элемент, объединив его значения.
collection.reduce((rr, ii) => rr.mergeWith((aa, bb) => List().concat(aa, bb), ii))