# I'd like to take the element of the same index from multiple lists

Is there a way to take multiple lists and get all the elements at their n th index and pass them to the function?
For example, list1 (= [1,3,5]) and list2 (= [2,4,6]) are added,then list (=[3,7,11]) is created.
What I wrote below is wrong, but I imagine such usage.

``````defmodule TwoLists do
def sum(list1,list2) do
Enum.map(list1,list2,fn(a,b)->a+b end)
end
end

iex> list1 = [1,3,5]
iex> list2 = [2,4,6]
iex> TwoLists.sum(list1,list2)
#-->Enum.map/3 is undefined error

``````

I’d like you to show me the way to implement.
Thanks

One way I see is the following one:

``````defmodule ListSum do
def sum(list1, list2, total \\ [])

def sum([], [], total) do
Enum.reverse(total)
end

def sum([h1 | t1], [], total) do
sum(t1, [], [h1 | total])
end

def sum([], [h2 | t2], total) do
sum([], t2, [h2 | total])
end

def sum([h1 | t1], [h2 | t2], total) do
sum(t1, t2, [h1 + h2 | total])
end
end
``````

This implementation has the advantage to work with list of different lengths.
You can also code an implement using `for` and `Enum.at` but lists must have same length is this case

6 Likes

You might use Enum.zip.

``````iex(1)> list1 = [1,3,5]
[1, 3, 5]
iex(2)> list2 = [2,4,6]
[2, 4, 6]
iex(3)> Enum.zip list1, list2
[{1, 2}, {3, 4}, {5, 6}]
iex(4)> list3 = [2,4,6,8]
[2, 4, 6, 8]
iex(5)> Enum.zip list1, list3
[{1, 2}, {3, 4}, {5, 6}]
``````

but it will return a number of elements corresponding to the smallest list in case they are not the same length.

You can use more than two lists

``````iex(6)> Enum.zip [list1, list2, list3]
[{1, 2, 2}, {3, 4, 4}, {5, 6, 6}]
``````

``````iex(7)> list1 |> Enum.zip(list2) |> Enum.map(& (elem(&1, 0) + elem(&1, 1)))
[3, 7, 11]
``````
3 Likes

I think this is very smart way to solve my problem.

Yes, I solved it by using `Enum.at` as below, but length of these lists must be same like you said.

``````def MultiLists(list1,list2) do
Enum.map(0..length(list1)-1,fn(n)->
Enum.at(list1,n) + Enum.at(list2,n)
end)
end
``````

Thanks. I learned a lot.

Thank you so much for lucid explanation.
I have never used `Enum.zip`, so I didn’t think of your nice idea.
I have to be careful about length of lists in this method.

Thanks, I try to use `Enum.zip` more.

This is terrible solution, because `Enum.at/2` has linear complexity. So in your case the complexity of this function is quadratic instead of linear.

3 Likes

Definitely go with @domvas’ solution. It runs faster and doesn’t break when lists are of different length.

1 Like

This is such an elegant solution! I know it works but I’m trying to understand exactly how, and have a very basic question to ask: I’ve never seen a function def not followed by do…end like the first def in this module; what does it mean? Thank you!

the function without the `do` block is a header function, it is needed when we declare default arguments on matching functions, see that only that function has the `total` with a default value. Without it you would get a `definitions with multiple clauses and default values require a header.` error message from the compiler.
Roughly the compiler will create a `sum/2` function calling the matching functions `sum/3` with a default value on the third argument.

You can see more examples at Elixir School.

2 Likes