Reputation: 4725
I have this:
a1 = [%{id: 1, val: 12}, %{id: 3, val: 7}, %{id: 1, val: 5}, %{id: 2, val: 3}, %{id: 2, val: 5}], %{id: 1, val: 3}]
How can I get this?
%{
1 => 20,
2 => 8,
3 => 7
}
That is, a sum of "val" of each item grouped by "id"
Should I first actually group them by "id"?
Enum.group_by a1, &(&1.id)
# =>
%{
1 => [%{id: 1, val: 12}, %{id: 1, val: 3}, %{id: 1, val: 5}],
2 => [%{id: 2, val: 3}, %{id: 2, val: 5}],
3 => [%{id: 3, val: 7}]
}
And then do map
and reduce
on each item? Or is there a better way?
Upvotes: 2
Views: 992
Reputation: 222128
I'd do it like this, with a single Enum.reduce/3
call:
[%{id: 1, val: 12}, %{id: 3, val: 7}, %{id: 1, val: 5}, %{id: 2, val: 3}, %{id: 2, val: 5}, %{id: 1, val: 3}]
|> Enum.reduce(%{}, fn %{id: id, val: val}, map ->
Map.update(map, id, val, &(&1 + val))
end)
|> IO.inspect
Output:
%{1 => 20, 2 => 8, 3 => 7}
This should be much more efficient than group_by
+ map
+ reduce
.
Upvotes: 8