2016-01-14 4 views
9

Я пытаюсь отсортировать список кортежей, как эти:Сортировка на различных уровнях в Python

[('Pineapple', 1), ('Orange', 3), ('Banana', 1), ('Apple', 1), ('Cherry', 2)] 

отсортированный список должен быть:

[('Orange', 3), ('Cherry', 2), ('Apple', 1), ('Banana', 1), ('Pineapple', 1)] 

Итак, вот первый список должен быть отсортирован на основании tuple[1] в порядке убывания, тогда, если значения tuple соответствуют Apple, ng порядок.

Я попытался возможно ways-

top_n.sort(key = operator.itemgetter(1, 0), reverse = True) 
# Output: [(Orange, 3), (Cherry, 2), (Pineapple, 1), (Banana, 1), (Apple, 1)] 

"reverse = True", как, ананас, затем банан, ...

я, наконец, пришлось придумать решение:

top_n.sort(key = operator.itemgetter(0), reverse = False) 
top_n.sort(key = operator.itemgetter(1), reverse = True) 

Есть ли лучший способ добраться до решения, как мой первый подход. Я пытаюсь изучить больше о Python, таким образом, ищет такое решение.

+0

На самом деле вы можете просто сделать: 'top_n.sort(); top_n.sort (key = itemgetter (1), reverse = True) '. Потому что 'reverse = False' является значением по умолчанию. Также использование 'itemgetter (0)' на самом деле не имеет особого смысла, поскольку последовательности уже отсортированы первым элементом, поэтому вы можете просто избегать использования 'key'. – Bakuriu

+0

@ Бакуриу: Да! Правда. Спасибо за предложение. –

ответ

2

В вашем случае решение Мартейн Питерс, вероятно, лучше, но я рассматриваю то, что вы могли бы сделать, если вам необходимо сделать это для любого числа параметров, и необходимо сделать некоторые восходящий и некоторый нисходящий.

Этот подход создает функцию для генерации индекса сортировки на лету. Вызов функции getsortfunction со списком кортежей для сортировки и список, содержащий индексы, и если они должны быть в обратном порядке (например, (2,True) означает второй индекс в обратном порядке), возвращает функцию, которая создает индекс сортировки для объекта. Это довольно уродливый, но универсален.

def getsortfunction(values,indices): 
    sorts = [sorted(list(set(x[indices[i][0]] for x in values)),reverse=indices[i][1]) for i in range(len(indices))] 
    def sortfunction(y): 
     return tuple(sorts[i].index(y[indices[i][0]]) for i in range(len(indices))) 
    return sortfunction 

Примеров

a = [('Pineapple',1),('Orange',3),('Banana',1),('Apple',1),('Cherry',2)] 
# sort a by index 1 first (in reverse order) and then by index 0 in non-reverse order 
b = sorted(a,key=getsortfunction(a,[(1,True),(0,False)])) # gives desired list 

с дополнительными критериями

c = [('Pineapple',1,'Hawaii'),('Orange',3,'Florida'),('Banana',1,'Hawaii'),('Apple',1,'Washington'),('Cherry',2,'Washington')] 
# sort first by number (in reverse order) then by state, and finally by fruit 
d = sorted(c,key=getsortfunction(c,[(1,True),(2,False),(0,False)])) 

# sort c first by number (in reverse order), then by fruit, ignoring state 
e = sorted(c,key=getsortfunction(c,[(1,True),(0,False)])) 

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

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

+0

Это то решение, которое я пытался, но я подумал, что, возможно, я переусердствовал (новичок в Python) и остановил его. Хотя это немного уродливо, я считаю, что это эффективное решение. Спасибо! –

13

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

top_n.sort(key=lambda t: (-t[1], t[0])) 

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

Демо:

>>> top_n = [('Pineapple', 1), ('Orange', 3), ('Banana', 1), ('Apple', 1), ('Cherry', 2)] 
>>> sorted(top_n, key=lambda t: (-t[1], t[0])) 
[('Orange', 3), ('Cherry', 2), ('Apple', 1), ('Banana', 1), ('Pineapple', 1)] 
+1

Единственная проблема с этим решением заключается в том, что отрицание работает только для целых чисел. Я не могу предложить ничего лучшего, мое решение было таким же. – fodma1

+0

Что делать, если оба аргумента были строками? – Arman

+3

@Arman: дальнейший взлом: преобразование строки в последовательность целых чисел с отрицанием ('[-chr (c) для c в строке]'). –

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

  • Нет связанных вопросов^_^