Harrygr

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

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

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

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))

Where Next?

Popular in Questions Top

aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call t...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New

Other popular topics Top

sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement