patternMinor
Return a grouped sum from a list
Viewed 0 times
returngroupedsumlistfrom
Problem
I just started with Elixir and this is what I have now. Is there an easier or better way to write this?
defmodule GroupBySum do
def sum(col), do: sum(%{}, col)
defp sum(r, [h|t]) do
{k, v} = h
r = r |> Dict.update(k, v, fn(val) -> val + v end)
sum(r, t)
end
defp sum(r, []), do: r
end
list = [a: 1, b: 2, c: 3, a: 2, b: 1, c: 0]
IO.inspect GroupBySum.sum(list) #%{a: 3, b: 3, c: 3}Solution
It can be done several ways. Instead of explicitly using recursion we can, as @alxndr suggested, make use of the recursion capabilities of the
In general the solution is the same as yours.
The anonmous function in map_reduce accepts and item and an accumulator. Since the item is a keyword list, it has the form
In the case of the input you provided, the
I found this a fun exercise -- thanks for posting.
Enum module. I am going to use Enum.map_reduce simply because I find it useful when troubleshooting to key the items and the accumulator in that form.In general the solution is the same as yours.
def sum(list) do
list |> Enum.map_reduce([],
fn({key, val}, acc) ->
{{key, val}, Keyword.update(acc, key, val, &(&1 + val))}
end
) |> elem(1)
endThe anonmous function in map_reduce accepts and item and an accumulator. Since the item is a keyword list, it has the form
{key,val} so I match that in the function definition. The return from this function must be a tuple with the accumulator as the second value. For testing purposes I returned the same {key, val} as the first item. The Keyword.update function is the accumulator. A form of this same routine that helps the intermediate values be visible is:def sum(list) do
list |> Enum.map_reduce([],
fn({key, val}, acc) ->
x = Keyword.update(acc, key, val, &(&1 + val))}
IO.inspect(x)
{{key, val}, x}
end
) |> elem(1)
endIn the case of the input you provided, the
IO.inspect helps me understand how the routine collected the desired result, as seen below.[a: 1]
[a: 1, b: 2]
[a: 1, b: 2, c: 3]
[a: 3, b: 2, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]I found this a fun exercise -- thanks for posting.
Code Snippets
def sum(list) do
list |> Enum.map_reduce([],
fn({key, val}, acc) ->
{{key, val}, Keyword.update(acc, key, val, &(&1 + val))}
end
) |> elem(1)
enddef sum(list) do
list |> Enum.map_reduce([],
fn({key, val}, acc) ->
x = Keyword.update(acc, key, val, &(&1 + val))}
IO.inspect(x)
{{key, val}, x}
end
) |> elem(1)
end[a: 1]
[a: 1, b: 2]
[a: 1, b: 2, c: 3]
[a: 3, b: 2, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]
[a: 3, b: 3, c: 3]Context
StackExchange Code Review Q#105881, answer score: 5
Revisions (0)
No revisions yet.