2015-02-23 3 views
1

У меня есть список кортежей из k элементов. Я хотел бы сортировать по элементу 0, затем по элементу 1 и т. Д. И так далее. Я googled, но я все еще не могу понять, как это сделать. Было бы что-то вроде этого?сортировать список кортежей с несколькими критериями

list.sort(key = lambda x : (x[0], x[1], ...., x[k-1]) 

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

+2

'list.sort()' должно быть достаточно. – vaultah

+0

Как и было предложено: используйте list.sort(). Попробуйте отсортировать список простых элементов, затем список кортежей первым элементом, затем список кортежей вторым элементом. Объедините свои знания. – dmitri

ответ

1

С python's sort is stable for versions after 2.2 (или perhaps 2.3), самой простой реализацией, я думаю, является последовательным повторением sort с использованием ряда index, reverse_value кортежей:

# Specify the index, and whether reverse should be True/False 
sort_spec = ((0, True), (1, False), (2, False), (3, True)) 

# Sort repeatedly from last tuple to the first, to have final output be 
# sorted by first tuple, and ties sorted by second tuple etc 
for index, reverse_value in sort_spec[::-1]: 
    list_of_tuples.sort(key = lambda x: x[index], reverse=reverse_value) 

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

Если порядок сортировки индексов действительно равен 0, 1... n-1, n для списка кортежей n-размера, как показано в вашем примере, тогда вам потребуется только последовательность True и False, чтобы указать, хотите ли вы reverse или нет, и вы можете используйте enumerate, чтобы добавить индекс.

sort_spec = (True, False, False, True) 
for index, reverse_value in list(enumerate(sort_spec))[::-1]: 
    list_of_tuples.sort(key = lambda x: x[index], reverse=reverse_value) 

В то время как исходный код допускал гибкость сортировки по любому порядку индексов.

Кстати, этот метод «последовательности сортов» рекомендуется в Python Sorting HOWTO с небольшими изменениями.

Редактировать Если у вас не было требование сортировки по возрастанию по некоторым показателям и убывания других, то

from operator import itemgetter 
list_of_tuples.sort(key = itemgetter(1, 3, 5)) 

будет сортировать по индексу 1, то связи будут отсортированы по индексу 3, и дальнейшие связи по индексу 5. Однако изменение восходящего/нисходящего порядка каждого индекса является нетривиальным в один проход.

0

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

ctr = 0 
for i in range(list_of_tuples): 
    if ctr%2 == 0: 
     list_of_tuples[0] = sorted(list_of_tuples[0]) 
    else: 
     list_of_tuples[0] = sorted(list_of_tuples[0], reverse=True) 
    ctr+=1 

print list_of_tuples 
+0

'для ctr, i в перечислении (диапазон (list_of_tuples))' может быть лучше –

1
list.sort(key = lambda x : (x[0], x[1], ...., x[k-1]) 

Это на самом деле использует кортеж в качестве своего собственного ключа сортировки. Другими словами, то же самое, что и вызов sort() без аргументов.

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

list.sort(key = lambda x : (x[k-1], x[1], ...., x[0]) 

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

Заключительный трюк (этот вопрос не в тему, но он может помочь вам в какой-то момент): при использовании библиотеки, которая не поддерживает идею «сортировки», вы можете получить такой же эффект, создав список, содержащий ключ сортировки. Итак, вместо сортировки списка Obj, вы построили бы потом сортировку списка кортежей: (ObjSortKey, Obj). Кроме того, просто вставка объектов в отсортированный набор будет работать, если они сортируют ключ уникальным. (Ключ сортировки будет индекс, в этом случае.)

Смежные вопросы