Elixir 创建地图时创建列表的列表
我写 列表如下所示Elixir 创建地图时创建列表的列表,elixir,Elixir,我写 列表如下所示 Enum.reduce(list, map, fn elem, map -> key=hd(elem) Map.put(map, key, List.wrap(Map.get(map, key)) ++ tl(elem)) end) 预期结果如下所示 ['B2', ['B1', 'B2', 'B3']], ['B2', ['A1', 'A2', 'A3']], 上面的代码确实产生了这个结果,但感觉异常难看 我觉得Enum.into可以用于更好的变体,但似乎我
Enum.reduce(list, map, fn elem, map ->
key=hd(elem)
Map.put(map, key, List.wrap(Map.get(map, key)) ++ tl(elem))
end)
预期结果如下所示
['B2', ['B1', 'B2', 'B3']],
['B2', ['A1', 'A2', 'A3']],
上面的代码确实产生了这个结果,但感觉异常难看
我觉得Enum.into
可以用于更好的变体,但似乎我无法同时掌握这些值。我试过了
B2 => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']]
但这并没有产生任何有用的结果。我相信我的大脑很难摆脱我在过去四分之一世纪的编码中所使用的命令式思维方式。我也会使用
Enum.reduce/3
,但不是Map.put/3
+List.wrap/1
,我会使用Map.update/4
,而不是hd/1
和tl/1
进行一些模式匹配
Enum.into(list, map, fn [k, v] -> {k, List.wrap(Map.get(map, k)) ++ v} end )
输出:
list = [
['A2', ['B1', 'B2', 'B3']],
['A2', ['A1', 'A2', 'A3']],
['B2', ['B1', 'B2', 'B3']],
['B2', ['A1', 'A2', 'A3']],
]
list
|> Enum.reduce(%{}, fn [k | v], acc ->
Map.update(acc, k, v, &(&1 ++ v))
end)
|> IO.inspect
虽然
Enum.reduce/3
可以很好地解决这个问题,但我会使用Enum.group\u by/2
来阐明意图。(如果且仅是性能不是最高优先级:reduce
会更快。)
基于Dogbert的答案,我创建了自己的结构:
list = [
['A2', ['B1', 'B2', 'B3']],
['A2', ['A1', 'A2', 'A3']],
['B2', ['B1', 'B2', 'B3']],
['B2', ['A1', 'A2', 'A3']],
] # thanks @Dogbert for the input
list
|> Enum.group_by(&Kernel.hd/1)
|> Enum.into(%{}, fn {k, e} ->
{k, Enum.map(e, &List.last/1)}
end)
# %{'A2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']],
# 'B2' => [['B1', 'B2', 'B3'], ['A1', 'A2', 'A3']]}
现在我可以做了
defmodule MyStruct do
defstruct []
def fetch(map, key), do: :maps.find(key, map)
end
defimpl Collectable, for: MyStruct do
def into(original) do
{original, fn
source, {:cont, [k | v ]} -> Map.update(source, k, v, &(&1 ++ v))
source, :done -> source
end}
end
end
或者在理解中使用
到:%MyStruct{}
。一个列表
和映射
的示例值将有助于理解问题。添加了一个示例。我错过了映射.更新
上的初始值--我假定更新
只是更新。`(&1++v)`只是fn x->x++v end
的简写,如果我收集正确的话。
defmodule MyStruct do
defstruct []
def fetch(map, key), do: :maps.find(key, map)
end
defimpl Collectable, for: MyStruct do
def into(original) do
{original, fn
source, {:cont, [k | v ]} -> Map.update(source, k, v, &(&1 ++ v))
source, :done -> source
end}
end
end
defmodule MyModule
map=Enum.into(list, %MyStruct{})
end