【问题标题】:How do I transform a List of Maps into a Map of Maps in immutable.js?如何在 immutable.js 中将地图列表转换为地图地图?
【发布时间】:2015-06-16 21:33:41
【问题描述】:

假设我有一个 immutable.js List 像这样:

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

我想将其转换为如下所示的地图:

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

如何在 immutable.js 中以惯用方式将 xs 转换为 ys

惯用我的意思是任何中间结构都应该是 immutable.js 结构,我认为任何中间步骤都将使用 iterable composition 而不是创建全尺寸的中间表示。

编辑:我创建了一个jsperf benchmark 来比较目前提供的答案。两种非变异解决方案对我来说都相当地道。我可以坚持让投票决定选择的答案,或者坚持到我们收集到大致相同的惯用技术集合为止。

【问题讨论】:

  • 你真的想要地图的地图,还是你想要的对象地图?
  • @Bergi Map of Maps - 一直不可变。

标签: javascript immutable.js


【解决方案1】:

看起来像这样,但我不确定中间表示

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

PS 很奇怪,但是我只能用.toKeyedSeq,不能用.toKeyedIterable,这样比较合适。

【讨论】:

    【解决方案2】:

    您可以将输入列表缩减为新的 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; }, 
          {}));
    

    但这肯定不那么惯用。

    【讨论】:

    • 感谢您的合理回复!我认为这是最好的答案。但是当我比较每次迭代时更新 Map 与最后构建新 Map 的性能时,我一直看到第一种方法快了近 10%,这与你最后提到的相反:jsperf.com/immutable-js-list-of-maps-to-map-of-maps/1
    【解决方案3】:

    一种解决方案可能是使用 List 中的 Map 构造函数:

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

    【讨论】:

      【解决方案4】:

      您可以使用reduce 结合mergeWith 将地图列表交换为列表地图。

      通过将其值连接在一起来减少集合并合并每个新项目。

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

      【讨论】:

        猜你喜欢
        • 2022-01-01
        • 1970-01-01
        • 2020-07-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多