Harrygr
Iterating a list to compare all elements with each other
In imperative languages, if one wants to compare every element in an array with the other they can use nested loops where the inner loop starts from the iterator of the outer loop. This avoids comparing elements with each other twice.
E.g.
int best = 0
for (int i = 0; i < a.length; i++) {
for (int k = i + 1; k < a.length; k++) {
best = max(best, compare(a[i], a[k]))
}
}
In Elixir, say I wanted to compare every value in a list with the others and find the best score (according to some arbritrary comparison) I could do something like
Enum.reduce(big_list_of_things, 0, fn
a, best ->
max(
best,
Enum.reduce(big_list_of_things, fn b, inner_best -> max(inner_best, compare(a, b)) end)
)
end)
This works, but involves iterating more times than needed (On^2). How might one refactor this so the inner iteration only reduces over what’s left?
Most Liked
LostKobrakai
You can do the same with recursion:
list = [1, 2, 3, 4]
defmodule Rec do
def compare(list, acc \\ [])
def compare([_], acc) do
acc
|> Enum.reverse()
|> List.flatten()
end
def compare([cur | rest], acc) do
compare(rest, [Enum.map(rest, &{cur, &1}) | acc])
end
end
Rec.compare(list)
# [{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}]
And you can look at combinatorics: GitHub - tallakt/comb: Elixir combinatorics - permutations and combinations of lists · GitHub
LostKobrakai
Another option are streams:
list = [1, 2, 3, 4]
stream =
Stream.transform(list, list, fn _, [cur | rest] ->
{Enum.map(rest, &{cur, &1}), rest}
end)
Enum.into(stream, [])
# [{1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}]
gregvaughn
A for comprehension with two generators from the same source list and a filter can do the job
for x <- list, y <- list, x < y, reduce: 0, do: (best -> max(best, compare(x, y))
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
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








