如何在 Elixir 中映射和减少地图列表

arp*_*pit 1 functional-programming elixir phoenix-framework

有什么好方法可以映射和减少长生不老药的列表并将其转换为新列表。

要求: 1. 找到具有相同id 的地图: 2. 合并“role”键的值(即收集所有唯一值)。3. 对于所有其他映射(列表元素),不执行任何操作。

list = [%{"id": 1, "role": ["A", "B"]}, %{"id": 2, "role": ["B", "C"]}, %{"id": 1, "role": ["C", "A"]} ]
Run Code Online (Sandbox Code Playgroud)

需要在以下列表中进行转换:

ans_list = [%{"id": 1, "role": ["A", "B", "C"]}, %{"id": 2, "role": ["B", "C"]}]
Run Code Online (Sandbox Code Playgroud)

Dog*_*ert 5

您可以使用Enum.group_by/2进行分组id,然后对于每个组,将 传递roleEnum.flat_map/2Enum.uniq/1

list = [%{"id": 1, "role": ["A", "B"]}, %{"id": 2, "role": ["B", "C"]}, %{"id": 1, "role": ["C", "A"]} ]

list
|> Enum.group_by(&(&1.id))
|> Enum.map(fn {key, value} ->
  %{id: key, role: value |> Enum.flat_map(&(&1.role)) |> Enum.uniq}
end)
|> IO.inspect
Run Code Online (Sandbox Code Playgroud)

输出:

[%{id: 1, role: ["A", "B", "C"]}, %{id: 2, role: ["B", "C"]}]
Run Code Online (Sandbox Code Playgroud)

根据下面评论中的要求,以下是如何保留所有键/值对并仅修改role组中的第一项:

list =  [%{"id": 1, "role": ["A", "B"], "somekey": "value of the key 1"},
         %{"id": 2, "role": ["B", "C"], "somekey": "value of the key 2"},
         %{"id": 1, "role": ["C", "A"], "somekey": "value of the key 3"}]

list
|> Enum.group_by(&(&1.id))
|> Enum.map(fn {_, [value | _] = values} ->
  %{value | role: values |> Enum.flat_map(&(&1.role)) |> Enum.uniq}
end)
|> IO.inspect
Run Code Online (Sandbox Code Playgroud)

输出:

[%{id: 1, role: ["A", "B", "C"], somekey: "value of the key 1"},
 %{id: 2, role: ["B", "C"], somekey: "value of the key 2"}]
Run Code Online (Sandbox Code Playgroud)