Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Elixir 创建地图时创建列表的列表_Elixir - Fatal编程技术网

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