списки:usort для n-го элемента в кортеже

#erlang #sorting

Вопрос:

Мне нужно отсортировать кортежи в соответствии со вторым элементом каждого кортежа, но, по-видимому, usort/1 работает только с первым элементом. Поэтому я должен поменять местами элементы, использовать их и поменять местами обратно.Есть ли более простой способ?Также есть способ сортировки в порядке убывания (я знаю, что сортировку и реверсирование можно выполнить, но просто хочу знать).

Ответ №1:

Вы пробовали функцию keysort/2 (или ее аналог ukeysort/2)?

 > lists:reverse(lists:keysort(2, [{a,2}, {b,1}, {c, 3}])).
[{c,3},{a,2},{b,1}]
 

Если вы не сортируете очень большие списки, это, вероятно, самое читаемое решение, которое вы можете получить.

Ответ №2:

На самом деле, лучший ответ:

Существует вторая версия сортировки, которая использует функцию сортировки:

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

Ответ №3:

Улучшенная версия решения bmdhacks:

 lists:sort(fun(A, B) ->
                   {_, A2} = A,
                   {_, B2} = B,
                   A2 =< B2
           end, YourList).
 

Подчеркивания лучше, чем A1 и B1, потому что компилятор будет выдавать предупреждения
для них.

Чтобы отсортировать в порядке убывания, просто измените <= на >=.

Ответ №4:

Не должно быть слишком сложно написать свою собственную функцию сортировки (адаптированную из общего примера).:

 qsort([]) -> [];
qsort([Pivot|Tail]) ->
    {PivotFirst, PivotSecond} = Pivot,
    qsort([{FirstElement, SecondElement} || {FirstElement,SecondElement} <- Tail, SecondElement < PivotSecond])
           [Pivot]   
        qsort([{FirstElement, SecondElement} || {FirstElement,SecondElement} <- Tail, SecondElement >= PivotSecond]).