在 Elixir 的嵌套地图中交换键
Swap keys in nested map in Elixir
我在 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
}
保证所有顶级键都包含同一组嵌套键。
有什么好的、简单的方法可以完成这种转换,我能够以某种方式实现它,但它并没有给我留下真正的印象漂亮。
坦率地说,我怀疑是否有超级优雅的解决方案。我会使用嵌套 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
|> 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 的回答更优雅,可能更有效。
我自己喜欢遍历嵌套数据的理解。
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
我在 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
}
保证所有顶级键都包含同一组嵌套键。
有什么好的、简单的方法可以完成这种转换,我能够以某种方式实现它,但它并没有给我留下真正的印象漂亮。
坦率地说,我怀疑是否有超级优雅的解决方案。我会使用嵌套 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
|> 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 的回答更优雅,可能更有效。
我自己喜欢遍历嵌套数据的理解。
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