Reputation: 1532
Does Erlang have the equivalent of Ruby's min_by?
Suppose I have a list:
[
[{right, 1}, {up, 5}, {left, 4}], %element 1
[{up, 2}, {right, 3}, {down, 1}], %element 2
... % element N
]
And a function that maps each of these elements to a scalar, such as:
f([{right, 1}, {up, 5}, {left, 4}]) -> 78.
f([{up, 2}, {right, 3}, {down, 1}]) -> 6.
Now I want to find the element that maps to the smallest value. In this example, I want to find [{up, 2}, {right, 3}, {down, 1}]
.
How can Erlang's standard library help me with this?
Upvotes: 1
Views: 70
Reputation: 26121
You can use fact that all Erlang terms are comparable and tuple has dictionary order.
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).
Upvotes: 0
Reputation: 222198
There isn't a builtin function to do exactly this, but you can write a simple tail recursive function for this that would be as efficient as possible in pure 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
Upvotes: 1