How to add list of nested maps?

I have a list of map something like this

[
  %{a: 1, b: 2, c: %{x: 1, y: 2}}, 
  %{a: 3, b: 4, c: %{x: 2, y: 3}},
  %{a: 5, b: 6, c: %{x: 3, y: 4}}
]

here I want to take the key “c” and add whatever is there on the map and return something like this

[
%{a: 1, b: 2, c: 3},
%{a: 3, b: 4, c: 5},
%{a: 5, b: 6, c: 7}
]

So what I did is something like this

a |> Enum.map(fn a -> a.c end) |> Enum.map(fn a -> Enum.reduce(a, 0, fn({_k, v}, acc) -> v + acc end) end)

First I’m mapping over the key “c” then I’m trying to map over the “c” values and adding them one by one. Its resulting me this [3, 5, 7]

But I’m not able to figure out the next step to achieve my solution. Also, this seems very expensive. Is there a better way?

Yes there is…

You could do this in one iteration.

  • Enum.map over the list (why do You use a? because it’s not an array)
  • Transform the c key of the map argument with the sum of the values of c
1 Like

Something like this would work:

[
  %{a: 1, b: 2, c: %{x: 1, y: 2}}, 
  %{a: 3, b: 4, c: %{x: 2, y: 3}},
  %{a: 5, b: 6, c: %{x: 3, y: 4}}
] |> Enum.map(fn m ->
  %{m | c: Enum.reduce(m.c, 0, fn {_k, v}, acc -> v + acc end )}
end)

It doesn’t work in your example because when you do Enum.map(fn a -> a.c end), the rest of the pipeline is now dealing with a list of c, and you’ve effectively lost the original map.

3 Likes

Mine is like this…

iex> Enum.map a, fn map -> %{map | c: map.c |> Map.values |> Enum.sum()} end
[%{a: 1, b: 2, c: 3}, %{a: 3, b: 4, c: 5}, %{a: 5, b: 6, c: 7}]
# or the short version
iex> Enum.map a, & %{&1 | c: &1.c |> Map.values |> Enum.sum()}
1 Like

I’m concerned about the performance. how many records it can handle? can I test it in some way?

The usual tool is benchee

Thanks :slight_smile:

Hi. I did not understand this part. What happens if “c” is also a list of maps?