Сортировка списка Python по двум полям



У меня есть следующий список, созданный из отсортированного csv



list1 = sorted(csv1, key=operator.itemgetter(1))


Я бы хотел отсортировать список по двум критериям: сначала по значению в поле 1, а затем по значению в поле 2. Как мне это сделать?

657   5  

5 ответов:

такой:

import operator
list1 = sorted(csv1, key=operator.itemgetter(1, 2))

ответ на этот мертвый поток для архива.

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

sorted(list, key=lambda x: (x[0], -x[1]))

Python имеет стабильную сортировку, поэтому при условии, что производительность не является проблемой, самый простой способ-отсортировать ее по полю 2, а затем снова отсортировать по полю 1.

это даст вам результат, который вы хотите, единственная загвоздка заключается в том, что если это большой список (или вы хотите сортировать его часто) вызов сортировки дважды может быть неприемлемым накладным расходом.

list1 = sorted(csv1, key=operator.itemgetter(2))
list1 = sorted(list1, key=operator.itemgetter(1))

делая это таким образом, также позволяет легко справиться с ситуацией, когда вы хотите, чтобы некоторые столбцы были отсортированы в обратном порядке, просто включите параметр 'reverse=True' при необходимости.

в противном случае вы можете передать несколько параметров itemgetter или вручную построить кортеж. Это, вероятно, будет быстрее, но проблема в том, что он не обобщает хорошо, если некоторые столбцы хотят быть отсортированы в обратном порядке (числовые столбцы все еще могут быть отменены, отрицая их, но это останавливает сортировку стабильной).

поэтому, если вам не нужны столбцы с обратной сортировкой, перейдите к нескольким аргументам itemgetter, если вы можете, и столбцы не являются числовыми, или вы хотите сохранить стабильную сортировку для нескольких последовательных сортировок.

Edit: для комментаторов, у которых есть проблемы с пониманием того, как это отвечает на исходный вопрос, вот пример, который показывает, как именно стабильный характер сортировки гарантирует, что мы можем выполнять отдельные сортировки по каждому ключу и в конечном итоге данные сортируются по нескольким критериям:

DATA = [
    ('Jones', 'Jane', 58),
    ('Smith', 'Anne', 30),
    ('Jones', 'Fred', 30),
    ('Smith', 'John', 60),
    ('Smith', 'Fred', 30),
    ('Jones', 'Anne', 30),
    ('Smith', 'Jane', 58),
    ('Smith', 'Twin2', 3),
    ('Jones', 'John', 60),
    ('Smith', 'Twin1', 3),
    ('Jones', 'Twin1', 3),
    ('Jones', 'Twin2', 3)
]

# Sort by Surname, Age DESCENDING, Firstname
print("Initial data in random order")
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred''')
DATA.sort(key=lambda row: row[1])

for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.''')
DATA.sort(key=lambda row: row[2], reverse=True)
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

print('''
Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.
''')
DATA.sort(key=lambda row: row[0])
for d in DATA:
    print("{:10s} {:10s} {}".format(*d))

это запускаемый пример, но чтобы спасти людей, работающих с ним вывод:

Initial data in random order
Jones      Jane       58
Smith      Anne       30
Jones      Fred       30
Smith      John       60
Smith      Fred       30
Jones      Anne       30
Smith      Jane       58
Smith      Twin2      3
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Jones      Twin2      3

First we sort by first name, after this pass all
Twin1 come before Twin2 and Anne comes before Fred
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Jones      Jane       58
Smith      Jane       58
Smith      John       60
Jones      John       60
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Second pass: sort by age in descending order.
Note that after this pass rows are sorted by age but
Twin1/Twin2 and Anne/Fred pairs are still in correct
firstname order.
Smith      John       60
Jones      John       60
Jones      Jane       58
Smith      Jane       58
Smith      Anne       30
Jones      Anne       30
Jones      Fred       30
Smith      Fred       30
Smith      Twin1      3
Jones      Twin1      3
Smith      Twin2      3
Jones      Twin2      3

Final pass sorts the Jones from the Smiths.
Within each family members are sorted by age but equal
age members are sorted by first name.

Jones      John       60
Jones      Jane       58
Jones      Anne       30
Jones      Fred       30
Jones      Twin1      3
Jones      Twin2      3
Smith      John       60
Smith      Jane       58
Smith      Anne       30
Smith      Fred       30
Smith      Twin1      3
Smith      Twin2      3

обратите внимание, в частности, как во втором шаге reverse=True параметр сохраняет первые имена в порядке, тогда как просто сортировка, а затем реверсирование списка потеряет желаемый порядок для третьего ключа сортировки.

def keyfunc(x):
    return tuple(x[1],x[2])

list1 = sorted(csv1, key=keyfunc)
employees.sort(key = lambda x:x[0])
employees.sort(key = lambda x:x[1])

мы также можем использовать .сортировка с лямбда 2 раза, потому что сортировка python-это сортировка на месте.Это будет сначала сортировать по первому элементу, а затем второй элемент. employees[0] = имя сотрудника сотрудники[1] = зарплата сотрудника

Comments

    Ничего не найдено.