Jodimoro
Jodimoro

Reputation: 4725

List of maps to a map with summing up values

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

Answers (1)

Dogbert
Dogbert

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

Related Questions