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

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

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

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

Ответ 1

вот так:

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

Ответ 2

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

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

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

Ответ 3

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

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

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

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

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

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

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

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 сохраняет первые имена в порядке, тогда как просто сортировка, а затем изменение списка приведет к потере желаемого порядка для третьего ключа сортировки.

Ответ 4

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

list1 = sorted(csv1, key=keyfunc)

Ответ 5

employees.sort(key = lambda x:x[1])
employees.sort(key = lambda x:x[0])

Мы также можем использовать .sort с лямбдой 2 раза, потому что сортировка Python установлена и стабильна. Сначала будет отсортирован список по второму элементу x [1]. Затем будет отсортирован первый элемент, x [0] (самый высокий приоритет).

сотрудники [0] = имя сотрудника сотрудники [1] = зарплата сотрудника

Это эквивалентно выполнению следующих действий: employee.sort(key = lambda x: (x [0], x [1]))

Ответ 6

Предположим, вы хотите отсортировать массив строк, содержащих числа, например, из

["date_2015-1-1", "date_2015-1-10", "date_2015-1-2"]

to

["date_2015-1-1", "date_2015-1-2", "date_2015-1-10"]

Вы можете сделать это следующим образом:

import re

def sort_key(_str): 
    return [ int(s) if s.isdigit() else s for s in re.split(r'(\d+)', _str) ]

arr = ["date_2015-1-1", "date_2015-1-10", "date_2015-1-2"]
sorted(arr, key=sort_key)

Ответ 7

Сортировка списка диктов с использованием приведенного ниже списка приведет к сортировке списка в порядке убывания по первому столбцу по зарплате и по второму столбцу по возрасту.

d=[{'salary':123,'age':23},{'salary':123,'age':25}]
d=sorted(d, key=lambda i: (i['salary'], i['age']),reverse=True)

Вывод: [{'salary': 123, 'age': 25}, {'salary': 123, 'age': 23}]

Ответ 8

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

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]))

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

sorted_data= sorted(non_sorted_data, key=lambda k: (k[1],k[0]),reverse=True)