lists: usort для n-го элемента в кортеже
Вопрос
Мне нужно отсортировать кортежи по второму элементу каждого кортежа, но, очевидно, usort / 1 работает только с первым элементом. Поэтому я должен поменять местами элементы, отсортировать их и поменять местами. Есть ли более простой способ? Также есть способ сортировки в порядке убывания (я знаю, что сортировка и обращение могут быть выполнены, но я просто хочу знать).
Решение
Пробовали ли вы использовать keysort / 2 функцию (или его коллега ukeysort / 2 )?
> lists:reverse(lists:keysort(2, [{a,2}, {b,1}, {c, 3}])).
[{c,3},{a,2},{b,1}]
Если вы не сортируете очень большие списки, это, вероятно, самое читаемое решение, которое вы можете получить.
Другие советы
На самом деле, лучший ответ:
Существует вторая версия сортировки, которая принимает функцию сортировки:
lists:sort(Fun, List1) -> List2
Вот пример, который сортирует по второму элементу в кортеже:
lists:sort(fun(A, B) ->
{A1, A2} = A,
{B1, B2} = B,
if
A2 > B2 ->
false;
true ->
true
end
end, YourList).
Улучшенная версия решения bmdhacks:
lists:sort(fun(A, B) ->
{_, A2} = A,
{_, B2} = B,
A2 =< B2
end, YourList).
Подчеркивания лучше, чем A1 и B1, потому что компилятор выдаст предупреждения для тех.
Чтобы отсортировать в порядке убывания, просто измените < = на > =.
Не должно быть слишком сложно написать собственную функцию сортировки (адаптировано из общего примера):
qsort([]) -> [];
qsort([Pivot|Tail]) ->
{PivotFirst, PivotSecond} = Pivot,
qsort([{FirstElement, SecondElement} || {FirstElement,SecondElement} <- Tail, SecondElement < PivotSecond])
++ [Pivot] ++
qsort([{FirstElement, SecondElement} || {FirstElement,SecondElement} <- Tail, SecondElement >= PivotSecond]).