【问题标题】:Swap keys in nested map in Elixir在 Elixir 的嵌套映射中交换键
【发布时间】:2021-04-20 13:43:04
【问题描述】:

我在 Elixir 中有以下结构的嵌套地图:

%{
  key1: %{
    nkey1: val1,
    nkey2: val4
  },
  key2: %{
    nkey1: val2,
    nkey2: val5
  },
  key3: %{
    nkey1: val3,
    nkey2: val6
  }
}

我想将其转换为以下结构。

%{
  nkey1: %{
    key1: val1,
    key2: val2,
    key3: val3
  },
  nkey2: %{
    key1: val4,
    key2: val5,
    key3: val6
}

保证所有顶级键都包含相同的嵌套键集。

有什么好的、简单的方法可以进行这种转换,我能够以某种方式实现它,但它并没有让我觉得它真的很美丽

【问题讨论】:

  • 你在这里问了一个关于什么是“美丽”的主观问题。你能分享你想出的代码进行比较吗?

标签: algorithm hashmap elixir


【解决方案1】:

我自己喜欢遍历嵌套数据的理解。

for {key, nested} <- input, {nkey, value} <- nested, reduce: %{} do
  acc ->
    put_in(acc, [Access.key(nkey, %{}), key], value)
    # The Access functions are less-known, so you may prefer this for understandability:
    # Map.update(acc, nkey, %{key => value}, &Map.put(&1, key, value))
end

【讨论】:

  • 这当然是一条路。
【解决方案2】:

坦率地说,我怀疑是否有一个超级优雅的解决方案。我会使用嵌套的Enum.reduce/3

map = %{
  key1: %{nkey1: 1, nkey2: 4},
  key2: %{nkey1: 2, nkey2: 5},
  key3: %{nkey1: 3, nkey2: 6}
}

Enum.reduce(map, %{}, fn {k, v}, acc ->
  Enum.reduce(v, acc, fn {kk, vv}, acc ->
    Map.update(acc, kk, %{k => vv}, &Map.put(&1, k, vv))
  end)
end)
#⇒ %{nkey1: %{key1: 1, key2: 2, key3: 3},
#    nkey2: %{key1: 4, key2: 5, key3: 6}}

【讨论】:

  • 这很优雅,使用Map.update!
【解决方案3】:

与 Aleksei 的回答类似,我是这样做的:

map
|> Enum.reduce(%{}, fn {key, val}, acc ->
  Map.merge(acc, val |> Enum.reduce(%{}, fn {nkey, nval}, nacc ->
    Map.put(nacc, nkey, Map.new([{key, nval}]))
  end),
  fn _dkey, dval1, dval2 -> Map.merge(dval1, dval2) end)
end)

我认为 Aleksei 的回答更优雅,可能更有效。

【讨论】:

  • Map.new([{key, nval}])%{key =&gt; nval}.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-28
  • 1970-01-01
  • 2017-05-27
  • 2021-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多