У меня есть следующий список, созданный из отсортированного csv
list1 = sorted(csv1, key=operator.itemgetter(1))
На самом деле я хотел бы отсортировать список по двум критериям: сначала по значению в поле 1, а затем по значению в поле 2. Как мне это сделать?
Переведено автоматически
Ответ 1
При использовании лямбда-функций ничего импортировать не нужно. Следующая сортировка list выполняется по первому элементу, затем по второму элементу. Вы также можете выполнить сортировку, например, по возрастанию одного поля и по убыванию другого.:
В Python существует стабильная сортировка, поэтому при условии, что производительность не является проблемой, самый простой способ - отсортировать его по полю 2, а затем снова отсортировать по полю 1.
Это даст вам желаемый результат, единственная загвоздка в том, что если это большой список (или вы хотите сортировать его часто), то повторный вызов sort может оказаться неприемлемыми накладными расходами.
Выполнение этого способа также упрощает обработку ситуации, когда вы хотите, чтобы некоторые столбцы были отсортированы в обратном порядке, просто включите параметр 'reverse = True', когда это необходимо.
В противном случае вы можете передать несколько параметров в itemgetter или вручную создать кортеж. Вероятно, это будет быстрее, но проблема в том, что это плохо обобщает, если некоторые столбцы требуется отсортировать в обратном порядке (числовые столбцы все еще можно изменить, отрицая их, но это останавливает стабильность сортировки).
Итак, если вам не нужны столбцы с обратной сортировкой, перейдите по нескольким аргументам в itemgetter, если возможно, и столбцы не числовые, или вы хотите сохранить стабильность сортировки, перейдите к нескольким последовательным сортировкам.
Редактировать: Для комментаторов, у которых возникли проблемы с пониманием того, как это отвечает на исходный вопрос, вот пример, который точно показывает, как стабильный характер сортировки гарантирует, что мы можем выполнять отдельные сортировки по каждому ключу и в конечном итоге получать данные, отсортированные по нескольким критериям:
# 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 passall 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 сохраняет порядок имен, тогда как простая сортировка с последующим переворачиванием списка приведет к потере желаемого порядка для третьего ключа сортировки.