如何将some_maps = [%{"test" => [1]}, %{"test2" => [2]}, %{"test" => [3]}]
这样的地图列表转换为一个巨大的单一地图,并将其值合并?
single_map = %{"test" => [1, 3], "test2" => [2]}
由于我无法在for
之类的迭代中修改地图,所以我不知道如何构建此地图
在其他语言中,我会定义一个空地图并遍历列表并填充地图,但在功能上我认为我不知道如何做到这一点。
答案 0 :(得分:3)
这是一种方法:
Enum.reduce(some_maps, fn x, y ->
Map.merge(x, y, fn _k, v1, v2 -> v2 ++ v1 end)
end)
答案 1 :(得分:2)
reduce解决方案绝对是生产质量的答案。但是,既然您提到了函数式编程的难点,请考虑reduce的“long-hand”版本:
defmodule MapMerger do
# The api function takes a list of maps, and returns them merged together.
def merge(list_of_maps) do
# This is written with a second function to hopefully be easier to follow;
# these two functions could be collapsed using a default parameter
# for the accumulator.
do_merge(list_of_maps, %{})
end
# This is the base case, which will match after all maps have been processed
# and the list is empty:
defp do_merge([], acc), do: acc
# Next comes the actual iterator; we pull head (the first item in the list),
# process it, then recurse on the rest of the list and an updated accumulator
defp do_merge([head|rest], acc) do
updated_acc = Map.merge(acc, head)
do_merge(rest, updated_acc)
end
end
一旦你可以遵循这个,减少应该更容易思考 - 它不会修改任何东西,它只是不断地使用恰好是旧参数的更新版本的新参数。我的生产代码通常使用reduce
来完成这样的小工作,但是当reduce中的操作很复杂时,我通常会将reduce分解为一个更容易推理的正确函数,并且更容易用注释标记。
从原来的问题:
在其他语言中,我会定义一个空地图并遍历列表并填充地图
请注意,这是对merge
和do_merge
函数如何工作的合理描述。你并不像你所认为的那样在功能上思考。