Многоуровневая сортировка списка кортежей в python

#python #python-3.x #list #sorting #tuples

#python #python-3.x #Список #сортировка #кортежи

Вопрос:

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

 list1 = [('a', 1, 3), ('b', 1, 2), ('c', 2, 1)]
 

на основе 2-го (asc) и 3-го элемента (asc) каждого кортежа, что приводит к:

 [('b', 1, 2), ('a', 1, 3), ('c', 2, 1)]
 

Я попытался использовать:

 sorted(list1, key=lambda x: x[1], x[2])
 

но приводит к ошибке:

 SyntaxError: positional argument follows keyword argument
 

Комментарии:

1. Вам нужно lambda x:(x[1],x[2])

Ответ №1:

Вот как:

 list1 = [('a', 1, 3), ('b', 1, 2), ('c', 2, 1)]

print(sorted(list1, key=lambda x: (x[1], x[2])))
 

Вывод:

 [('b', 1, 2), ('a', 1, 3), ('c', 2, 1)]
 

Причина, по которой вы получаете ошибку, заключается в запятой в. Видите ли, вместо того, чтобы принимать его как часть lambda функции, python интерпретирует его, поскольку вы пытаетесь передать в функцию другой аргумент, фактически позиционный аргумент sorted .

При каждом вызове функции передача аргументов ключевого слова перед позиционными аргументами приведет к указанной вами ошибке.

 sorted(list1, key=lambda x: x[1], x[2])
 

Примечание: срез [1:] тоже работает:

 list1 = [('a', 1, 3), ('b', 1, 2), ('c', 2, 1)]

print(sorted(list1, key=lambda x: x[1:]))
 

Ответ №2:

Запятая в вашей ключевой лямбде выглядит как конец аргумента для синтаксического анализатора. Заключите его в скобки, чтобы устранить неоднозначность: key=lambda x: (x[1], x[2]) .

В качестве альтернативы, нарезка делает то же самое в этом случае : key=lambda x: x[-2:] .

Кроме того, хотя это не имеет значения для такого короткого списка operator.itemgetter , функция незначительно превосходит лямбда-выражение — в прошлый раз, когда я проверял, это было примерно на 10% быстрее в больших списках. key=operator.itemgetter(1, 2) .

Ответ №3:

Основываясь на сообщении об ошибке, похоже, что интерпретатор интерпретирует key=(lambda x:x[1]) и (x[2]) как второй и третий аргументы sorted() соответственно. Если вы поместите все лямбда-выражение в круглые скобки, оно должно работать.