How to return the function value along with the returned element from Enum.max_by in Elixir

How may we return the function value along with the returned element from Enum.max_by/3 in Elixir

I have this case:

def fuzzy_match(x, items) do
    m = Enum.max_by(items, fn i -> TheFuzz.compare(:jaro_winkler, x.desc, i.desc) end)
    IO.puts("fuzzy: #{inspect(m)}")
    m
end

It is not enough to know the best matching item, I also need to know the matching thresh hold and to eliminate poor matches below 0.7

With Enum.max_by/3 it is not possible to do this

Probably something like

  • map over the items generating the comparison value
  • store both in a tuple
  • have the max_by function only look at the result in the tuple to determine the winner

was thinking more along the lines max_by_with_value

Wouldn’t that just be a values |> Enum.map(...) |> Enum.max() or so?

Have you considered a fold?

1 Like
defmodule Demo do
  def max_by_with_value(items,fun) do
    with_compare_result = fn i -> {i, fun.(i)} end
    compare_result = fn {_,result} -> result end
    items
    |> Enum.map(with_compare_result)
    |> Enum.max_by(compare_result)
  end

  def foldl_impl([x|xs],fun) do
    f = fn (x, {_,value} = last) ->
      result = fun.(x)
      if result > value, do: {x,result}, else: last
    end
    List.foldl(xs, {x, fun.(x)}, f)
  end
end

fun = &(&1 |> String.graphemes() |> length())
items = ["a", "aaa", "aa"]
IO.inspect Demo.max_by_with_value(items, fun)
IO.inspect Demo.foldl_impl(items, fun)
1 Like

more like this https://stackoverflow.com/a/50049128/44080

have not tried that…

No point polluting the standard library with functions that

  • have minimal reusability and
  • can be fairly easily composed

… and reducing is folding

1 Like

i’m storing the found item, then re-running the function to get a value to return along with the found item