Як сортувати список / кортеж списків / кортежів за елементом за заданим індексом?


657

У мене є деякі дані або в списку списків, або в списку кортежів, таких як:

data = [[1,2,3], [4,5,6], [7,8,9]]
data = [(1,2,3), (4,5,6), (7,8,9)]

І я хочу сортувати по 2-му елементу в підмножині. Значення, сортування по 2,5,8 , де 2знаходиться з (1,2,3), 5від (4,5,6). Який загальний спосіб це зробити? Чи потрібно зберігати кортежі чи списки у своєму списку?


51
Що стосується "Чи потрібно зберігати кортежі чи списки у своєму списку?", Головне правило - зробити речі максимально непорушними. Якщо вам не потрібно змінювати підспіси на місці, зробіть їх кортежами.
Меттью Флашен

Відповіді:


1112
sorted_by_second = sorted(data, key=lambda tup: tup[1])

або:

data.sort(key=lambda tup: tup[1])  # sorts in place

10
Будь-яка ідея, як сортувати її до меншої?
billwild

63
@billwild: допомога (сортування). зворотний = Правда.
Стівен

34
@Stephen за допомогою itemgetter швидше і простіше: key=itemgetter(1)і на початку файлу:from operator import itemgetter
Joschua

3
@Cemre, як і для другого прикладу, sortтут є метод Listоб’єкта Python, який отримує функцію лямбда як свій keyпараметр. Ви можете назвати його як tup, або t, або що завгодно, і воно все одно буде працювати. tupтут вказується індекс кортежу списку, тобто 1означає, що сортування буде виконуватися за другими значеннями кортежів з вихідного списку ( 2, 5, 8).
Нейромедіатор

1
Я був скептично скептичний до необгрунтованого твердження, що "використовувати itemgetter швидше і простіше". У той час як я суб'єктивно вважаю інтуїтивний lambdaпідхід до більш простим , ніж неінтуітівнимі itemgetterкласу, itemgetter це дійсно , здається, швидше . Мені цікаво, чому це так. Моє грубе підозру полягає в тому, що пов'язана lambdaз прихованою вартістю захоплення всіх локальних змінних у контекст закриття, тоді як itemgetterпримірник цього не робить. tl; dr: Завжди використовуйте itemgetter, тому що швидкість перемагає.
Сесіль Карі

236
from operator import itemgetter
data.sort(key=itemgetter(1))

37
Це має бути прийнятою відповіддю. Дивіться також Charlie «s розмістив тайминги , демонструючи itemgetterклас для сортування 126% швидше , ніж у середньому еквівалентної lambdaфункції.
Сесіль Карі

9
Ви також можете сортувати за кількома індексами ієрархічно, наприкладdata.sort(key=itemgetter(3,1))
Michael Ohlrogge

57

Я просто хочу додати відповідь Стівена, якщо ви хочете сортувати масив від високого до низького, іншим способом, відмінним від коментарів вище, є лише додати це до рядка:

reverse = True

і результат буде таким:

data.sort(key=lambda tup: tup[1], reverse=True)

48

Для сортування за декількома критеріями, а саме, наприклад, за другим та третім елементами в кортежі, нехай

data = [(1,2,3),(1,2,1),(1,1,4)]

і так визначте лямбда, яка повертає кортеж, який описує, наприклад, пріоритет

sorted(data, key=lambda tup: (tup[1],tup[2]) )
[(1, 1, 4), (1, 2, 1), (1, 2, 3)]

28

Відповідь Стівена - той, який я б використав. Для повноти, ось ось шаблон DSU (прикрасити-сортувати-визначити) зі списком розумінь:

decorated = [(tup[1], tup) for tup in data]
decorated.sort()
undecorated = [tup for second, tup in decorated]

Або, більш коротко:

[b for a,b in sorted((tup[1], tup) for tup in data)]

Як зазначалося у програмі HowTo сортування Python , це було непотрібним з моменту Python 2.4, коли ключові функції стали доступними.


2
Тож ця відповідь корисна для Python 2.3-? Чи є дійсні способи використання у більш сучасних версіях Python, навколо яких ви можете трохи розробити? Якщо ні, не турбуйтеся ... щойно проїжджав мимо, побачив це, і старий ніггін дістався до того, як він просто бив. У будь-якому разі, привіт і спасибі за цю прогулянку назад у попередні дні Python.
механічний_міс

19

Для того, щоб сортувати список кортежів (<word>, <count>), countу порядку зменшення та wordв алфавітному порядку:

data = [
('betty', 1),
('bought', 1),
('a', 1),
('bit', 1),
('of', 1),
('butter', 2),
('but', 1),
('the', 1),
('was', 1),
('bitter', 1)]

Я використовую цей метод:

sorted(data, key=lambda tup:(-tup[1], tup[0]))

і це дає мені результат:

[('butter', 2),
('a', 1),
('betty', 1),
('bit', 1),
('bitter', 1),
('bought', 1),
('but', 1),
('of', 1),
('the', 1),
('was', 1)]

1
що робити, якщо tup [1] є рядком?
eric


9

itemgetter()дещо швидше lambda tup: tup[1], але збільшення порівняно скромне (близько 10 до 25 відсотків).

(Сеанс IPython)

>>> from operator import itemgetter
>>> from numpy.random import randint
>>> values = randint(0, 9, 30000).reshape((10000,3))
>>> tpls = [tuple(values[i,:]) for i in range(len(values))]

>>> tpls[:5]    # display sample from list
[(1, 0, 0), 
 (8, 5, 5), 
 (5, 4, 0), 
 (5, 7, 7), 
 (4, 2, 1)]

>>> sorted(tpls[:5], key=itemgetter(1))    # example sort
[(1, 0, 0), 
 (4, 2, 1), 
 (5, 4, 0), 
 (8, 5, 5), 
 (5, 7, 7)]

>>> %timeit sorted(tpls, key=itemgetter(1))
100 loops, best of 3: 4.89 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: tup[1])
100 loops, best of 3: 6.39 ms per loop

>>> %timeit sorted(tpls, key=(itemgetter(1,0)))
100 loops, best of 3: 16.1 ms per loop

>>> %timeit sorted(tpls, key=lambda tup: (tup[1], tup[0]))
100 loops, best of 3: 17.1 ms per loop

Будь ласка, перегляньте тут рішення сортування предметів для варіювання зворотних аргументів для кількох стовпців тут, тоді вам потрібно організувати своє сортування у кілька етапів поспіль: stackoverflow.com/questions/14466068/…
Lorenz

6

Відповідь @Stephen до речі! Ось приклад для кращої візуалізації,

Викрикуйте шанувальників Ready Player One! =)

>>> gunters = [('2044-04-05', 'parzival'), ('2044-04-07', 'aech'), ('2044-04-06', 'art3mis')]
>>> gunters.sort(key=lambda tup: tup[0])
>>> print gunters
[('2044-04-05', 'parzival'), ('2044-04-06', 'art3mis'), ('2044-04-07', 'aech')]

keyце функція, яка буде викликана для перетворення елементів колекції для порівняння .. як compareToметод у Java.

Параметр, переданий ключу, повинен бути те, що можна викликати. Тут використання lambdaстворює анонімну функцію (яку можна викликати).
Синтаксис лямбда - це слово лямбда, за яким слід ітерабельна назва, а потім - єдиний блок коду.

Нижче на прикладі ми сортуємо список кортежу, який містить інформаційний час про певну подію та ім'я актора.

Ми сортуємо цей список за часом виникнення події - це 0-й елемент кортежу.

Примітка - s.sort([cmp[, key[, reverse]]]) сортує елементи s на місці


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.