I am learning Elixir and found myself having to concat multiple lists together where I have a beginning, middle, and end. Simplified example:
a = [1,2]
b = [3,4]
c = [5,6]
a ++ b ++ c
> [1, 2, 3, 4, 5, 6]
I am doing this thousands of times in a stream and want to be Elixirific about it.
I wrote a function to handle this, there is probably something that does this for me, but I don't see it. Should I be using built-in Elixir function for this?
def append(front, back) when is_list(front) when is_list(back) do
front
|> Enum.reverse
|> Enum.reduce(back, &([&1 | &2]))
end
Or should I have just done this and it will become more natural for me over time?
[1, 2]
|> Enum.reverse
|> Enum.reduce([3, 4], &([&1 | &2]))
|> Enum.reverse
|> Enum.reduce([5, 6], &([&1 | &2]))
Does the order in which I call the parts together matter?
Way 1:
[1, 2]
|> append([3, 4])
|> append([5, 6])
...
Way 2:
end = append([3, 4], [5, 6])
append([1, 2], end)
Will the intermediary list be re-used in both scenarios since both are appending header pointers?
Any help on this would be great, cheers.
How do you add two lists in Elixir? Idiom #166 Concatenate two lists. Create the list ab containing all the elements of the list a, followed by all the elements of the list b. auto ab = a; ab.
In Elixir and Erlang we use `list ++ [elem]` to append elements.
No matter what approach you use, you will end up at cloning at least all lists except the last one, since you cannot append to a linked list without cloning it. So if you know you want to concatenate the lists (i.e. you cannot modify your code to accept a nested list like [a, b, c]
), I would suggest a ++ b ++ c
since ++
is implemented in Erlang's C code, which should be pretty much as fast as possible, and definitely faster than manually concatenating with Enum.reverse/1
and Enum.reduce/3
.
Here's a tiny microbenchmark comparing a ++ b ++ c
vs a |> append(b) |> append(c)
:
defmodule BasicBench do
use Benchfella
bench "++", [a: gen(), b: gen(), c: gen()] do
a ++ b ++ c
end
bench "append", [a: gen(), b: gen(), c: gen()] do
a |> append(b) |> append(c)
end
def append(front, back) when is_list(front) when is_list(back) do
front
|> Enum.reverse
|> Enum.reduce(back, &([&1 | &2]))
end
def gen, do: Enum.to_list(1..1000)
end
and the output:
benchma iterations average time
++ 100000 10.22 µs/op
append 20000 75.79 µs/op
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With