查找具有最小映射值的列表元素?

时间:2017-01-09 03:29:30

标签: erlang

Erlang是否相当于Ruby's min_by

假设我有一个清单:

[
  [{right, 1}, {up, 5}, {left, 4}], %element 1
  [{up, 2}, {right, 3}, {down, 1}], %element 2
  ... % element N
]

一个将每个元素映射到标量的函数,例如:

f([{right, 1}, {up, 5}, {left, 4}]) -> 78.
f([{up, 2}, {right, 3}, {down, 1}]) -> 6.

现在我想找到映射到最小值的元素。在此示例中,我想查找[{up, 2}, {right, 3}, {down, 1}]

Erlang的标准库如何帮助我?

2 个答案:

答案 0 :(得分:1)

没有内置函数可以做到这一点,但你可以为此编写一个简单的尾递归函数,它在纯Erlang中尽可能高效:

min_by([H|T], F) ->
  min_by(T, F, H, F(H)).

min_by([H|T], F, MinValue, MinMapped) ->
  case F(H) of
    NewMapped when NewMapped < MinMapped ->
      min_by(T, F, H, NewMapped);
    _ ->
      min_by(T, F, MinValue, MinMapped)
  end;
min_by([], _, MinValue, _) -> MinValue.
1> c(a).
{ok,a}
2> a:min_by([1, 2, 3], fun (2) -> 0; (_) -> 1 end).
2

答案 1 :(得分:1)

你可以使用所有Erlang术语都具有可比性且tuple具有字典顺序的事实。

MinBy = fun(L, F) ->
        {_, Min} = lists:min([{F(X), X} || X <- L]),
        Min
    end.
L = [
    [{right, 1}, {up, 5}, {left, 4}] %element 1
  , [{up, 2}, {right, 3}, {down, 1}] %element 2
].
F = fun([{right, 1}, {up, 5}, {left, 4}]) -> 78;
       ([{up, 2}, {right, 3}, {down, 1}]) -> 6
    end.
MinBy(L, F).