0
votes

Let's say that we have the following list of lists:

[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]

How to transform it to a list containing sum of each element on its corresponding position so that in the end the result is [5, 10, 15, 20] ?

1
Looking for a better solution than the one I have: [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]] |> Enum.zip |> Enum.map(fn x -> Enum.sum(Tuple.to_list(x)) end)leslie_s

1 Answers

0
votes

There is unlikely a more succinct variant available, but one might avoid iterating lists several times and do everything in one pass (and without involving tuples and conversions) using recursion.

transpose = fn 
  [[x | xs] | xss], fun -> 
    [[x | Enum.map(xss, &hd/1)] | fun.([xs | Enum.map(xss, &tl/1)], fun)]
  [[] | xss], fun -> fun.(xss, fun)
  [], _ -> []
end
#⇒ #Function<43.97283095/2 in :erl_eval.expr/5>

transpose.(lists, transpose)                                           
#⇒ [[1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4]]

lists |> transpose.(transpose) |> Enum.map(&Enum.sum/1)
#⇒ [5, 10, 15, 20]

or, even simpler, avoiding an intermediate transpose:

sum = fn 
  [[] | _], _ -> []
  xs, fun -> 
    [(xs |> Enum.map(&hd/1) |> Enum.sum()) |
      fun.(Enum.map(xs, &tl/1), fun)]
end

sum.(lists, sum)
#⇒ [5, 10, 15, 20]