【发布时间】:2017-10-04 00:45:49
【问题描述】:
如何在 elixir 中转换此列表
[
%{key1: 1, key2: 2, key3: 3},
%{key1: 4, key2: 5, key3: 6},
%{key1: 7, key2: 8, key3: 9}
]
到这张地图
%{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9])
?
【问题讨论】:
标签: elixir
如何在 elixir 中转换此列表
[
%{key1: 1, key2: 2, key3: 3},
%{key1: 4, key2: 5, key3: 6},
%{key1: 7, key2: 8, key3: 9}
]
到这张地图
%{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9])
?
【问题讨论】:
标签: elixir
您可以分两次执行此操作;第一个将所有内容扁平化为一个键值对的一维列表,然后第二个通过键进行分组。
input = [
%{key1: 1, key2: 2, key3: 3},
%{key1: 4, key2: 5, key3: 6},
%{key1: 7, key2: 8, key3: 9}
]
input
|> Enum.flat_map(fn m -> Map.to_list(m) end)
|> Enum.group_by(fn {k, _} -> k end, fn {_, v} -> v end)
输出
%{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
【讨论】:
Enum.reduce(input, %{key1: [], key2: [], key3: []}, fn m, acc ->
Map.merge(acc, m, fn _k, v1, v2 -> v1 ++ [v2] end)
end)
#⇒ %{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
或者,没有初步的硬编码累加器:
Enum.reduce(input, %{}, fn m, acc ->
Map.merge(acc, m, fn
_k, v1, v2 when is_list(v1) ->
:lists.reverse([v2 | :lists.reverse(v1)])
_k, v1, v2 -> [v1, v2]
end)
end)
#⇒ %{key1: [1, 4, 7], key2: [2, 5, 8], key3: [3, 6, 9]}
【讨论】:
还不是很擅长 Elixir,但我想出了这个:
map = Enum.reduce(list, %{}, fn(inner_map, acc) ->
Map.merge(acc, inner_map, fn(_, v1, v2) ->
if is_list(v1) do
v1 ++ [v2]
else
[v1] ++ [v2]
end
end)
end)
但我认为必须有更优雅的方式来做到这一点
【讨论】:
if。