franz909
franz909

Reputation: 192

How to sum up values of different keys in a list of maps in Elixir

Hello i want to sum up all count and all val keys, to a new map which contains the accumulated values of both keys.

This is what i've done so far:

list = [
  %{count: 1, val: 12},
  %{count: 3, val: 7},
  %{count: 1, val: 5},
  %{count: 2, val: 3},
  %{count: 2, val: 5},
  %{count: 1, val: 3}
]

x = &%{count: &1, val: &1}
sumCount = list |> Enum.reduce(0, &(&1.count + &2)) |> x.() |> IO.inspect()

I get this result:

#ouput: 
%{count: 10, val: 10}

But I need this result:

%{count: 10, val: 35}

I just know how to sum up just one key. Should I sum up the keys seperately in two functions? I think thats not performant, considering the list will have even more values/maps or maybe some more keys. Is there a efficient way to sum up all the keys at once?

Upvotes: 3

Views: 1774

Answers (3)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

I would go with reducing the initial list by Map.merge/3

Enum.reduce(list, &Map.merge(&1, &2, fn _, v1, v2 -> v1 + v2 end))
#⇒ %{count: 10, val: 35}

Upvotes: 5

Adam Millerchip
Adam Millerchip

Reputation: 23091

You can use Enum.reduce/2, because your list elements and accumulated value are the same format. The trick is to use the entire map %{count: count, val: val} as the accumulator, rather than just a single integer:

Enum.reduce(list, fn item, acc ->
  %{count: item.count + acc.count, val: item.val + acc.val}
end)

Upvotes: 5

Julien C
Julien C

Reputation: 230

I think this is what you're looking for?

Enum.reduce(list, %{count: 0, val: 0}, fn %{count: count, val: val}, acc ->
  %{count: acc.count + count, val: acc.val + val}
end)

Upvotes: 5

Related Questions