2017-01-09 3 views
2

Имеет ли 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

Вы можете использовать факт, что все термины Эрланга сопоставимы, а кортеж имеет порядок словаря.

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). 
+0

Черт, это изящно! – Philip

+0

@Philip: Элегантный, но немного менее эффективный, чем решение Добберта. –

2

Существует не встроенная функция, чтобы сделать именно это, но вы можете написать простой хвост рекурсивной функции для этого, что бы как можно более эффективно в чистом 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 
Смежные вопросы