В python как мы можем отсортировать список кортежей, указав desc / as c для каждого элемента? - PullRequest
0 голосов
/ 27 февраля 2020

В SQL мы можем указать desc / as c порядок для каждого ключа сортировки, т.е. order by key1 desc, key2 asc. Как мне добиться того же, чтобы отсортировать список кортежей в python?

Предположим, у меня есть список типа

[("a", "b", "e"), ("b", "a", "c"), ("b", "a", "d")]

Я хочу использовать второй ключ в качестве c порядок и третий ky в порядке c. Таким образом, результат равен

[("b", "a", "d"), ("b", "a", "c"), ("a", "b", "e")]

Обратите внимание, что элементы могут быть любого типа, которые имеют методы сравнения (т.е. __lt__, __gt__ et c)

Ответы [ 3 ]

3 голосов
/ 27 февраля 2020

Вам необходимо создать подходящую ключевую функцию для сортировки - см. Сортировка кортежей по второму параметру и множеству других

data = [("a", "b", "c"), ("b", "a", "c"), ("b", "a", "d")]


s = sorted(data, key = lambda x: (x[1],-ord(x[2]))) # "trick" to sort descending

print (s)

дает

[('b', 'a', 'd'), ('b', 'a', 'c'), ('a', 'b', 'c')]

Вы используете «настроенный» кортеж в качестве ключа и должны быть немного креативны при его создании.

Функция ord дает вам значение ascii персонажа, отрицая его, вы «сортируете по убыванию».

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


Серьезно не проверено:

data = [("a", "b", "cesa"), ("b", "a", "ceta"), ("b", "a", "derived")]
s = sorted(data, key = lambda x: (x[1], tuple((-ord(t) for t in x[2])) ) )

чтобы получить

[('b', 'a', 'derived'), ('b', 'a', 'ceta'), ('a', 'b', 'cesa')]
1 голос
/ 27 февраля 2020

Вы можете использовать две сортировки (они стабильны) в порядке уменьшения приоритета:

>>> from operator import itemgetter
>>> a = [("a", "b", "e"), ("b", "a", "c"), ("b", "a", "d")]

>>> a.sort(key=itemgetter(2), reverse=True)
>>> a.sort(key=itemgetter(1))

>>> a
[('b', 'a', 'd'), ('b', 'a', 'c'), ('a', 'b', 'e')]

В прошлый раз, когда я проверял, это было кстати быстрее , чем одиночная сортировка с более сложная ключевая функция. И она требует меньше памяти, чем ключевая функция, создающая новые кортежи.

См. Python ' Сортировка КАК для большего количества примеров этого.

1 голос
/ 27 февраля 2020

Я нашел способ создания класса сортировщика с пользовательскими методами сравнения. Это не эффективный способ, но работает нормально.

from functools import total_ordering


def _apply(v, k):
    if callable(k):
        return k(v)
    else:
        return v[k]


def smart_sort(xs, getters_and_orders):
    orders = []
    getters = []
    for x in getters_and_orders:
        if isinstance(x, tuple):
            g, o = x
        else:
            g = x
            o = "desc"
        getters.append(g)
        orders.append(o)

    @total_ordering
    class _Sorter:
        def __init__(self, v):
            self._values = [_apply(v, g) for g in getters]

        def __eq__(self, other):
            return self._values == other._values

        def __lt__(self, other):
            for (a, b, o) in zip(self._values, other._values, orders):
                if a != b:
                    return a > b if o == "desc" else a < b
            return False

    return sorted(xs, key=_Sorter)


xs = [("a", "b", "e"), ("b", "a", "c"), ("b", "a", "d")]
ret = smart_sort(xs, [(1, "asc"), (2, "desc")])
print(ret)

>> [('b', 'a', 'd'), ('b', 'a', 'c'), ('a', 'b', 'e')]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...