slouchpie
Efficient use of `reduce`
Imagine I have a simple list
my_list = [1, 2, 3]
and I want to “do something” to each element in a reduce loop, removing elements that error/fail while “doing something”.
It might look like this:
my_list
|> Enum.reduce([], fn x, acc ->
with {:ok, result: result} <- do_something(x) do
acc ++ [result]
else
_ -> acc
end
end)
That gets me the result I want.
However, I know that in Elixir it is more efficient to do [result] ++ acc than it is to do acc ++ [result].
So, for large lists, would it be more efficient to use [result] ++ acc in the reduce loop and then in my pipeline use Enum.reverse to put the list back in original order?
Marked As Solved
hauleth
Well, in this case I would use Enum.flat_map/2 instead (which behind the hood will do almost the same thing you are doing there with Enum.reverse/1.
Also Liked
NobbZ
The most efficient version to do this is probably doing [result|acc] and Enum.reverse after building the list.
wolf4earth
Alternatively to Enum.flat_map/2 you can use a for-comprehension:
for with 1-element list
for i <- my_list,
# We have to wrap the `do_something` call in a list to use `<-` for filtering
{:ok, result: result} <- [do_something(i)] do
result
end
for with filter clause
for i <- my_list,
ok_or_error = do_something(i),
match?({:ok, _}, ok_or_error) do
{:ok, result: result} = ok_or_error
result
end
cloud8421
Note that the compiler actually replaces [hd] ++ acc with [hd | acc] (see https://erlang.org/doc/efficiency_guide/myths.html#myth--operator--++--is-always-bad) so if you try to profile both versions you might not see any difference.
Last Post!
slouchpie
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









