Reputation: 19456
If I've got a collection of the form:
[{key, value}, {key, value2}, {key2, value3}]
how do I transform it to a map of the form
%{key => [value, value2], key2 => [value3]}
?
Upvotes: 1
Views: 50
Reputation: 121000
Reducing with Map.update/4
would be a good fit:
[{:key, :value}, {:key, :value2}, {:key2, :value3}]
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.update(acc, k, [v], fn l -> [v | l] end)
end)
#⇒ %{key: [:value2, :value], key2: [:value3]}
To preserve an order of lists, map to {k, Enum.reverse(n)}
afterwards.
[{:key, :value}, {:key, :value2}, {:key2, :value3}]
|> Enum.reduce(%{}, fn {k, v}, acc ->
Map.update(acc, k, [v], fn l -> [v | l] end)
end)
|> Enum.map(fn {k, v} -> {k, Enum.reverse(v)} end)
#⇒ %{key: [:value, :value2], key2: [:value3]}
Another option would be Enum.group_by/3
[{:key, :value}, {:key, :value2}, {:key2, :value3}]
|> Enum.group_by(&elem(&1, 0))
|> Enum.map(fn {k, v} -> {k, Keyword.values(v)} end)
|> Enum.into(%{})
#⇒ %{key: [:value, :value2], key2: [:value3]}
or, with a mapper:
[{:key, :value}, {:key, :value2}, {:key2, :value3}]
|> Enum.group_by(&elem(&1, 0), &elem(&1, 1))
#⇒ %{key: [:value, :value2], key2: [:value3]}
Upvotes: 2