Вопрос по python, list, tuples – Сортировать список кортежей по 2-му элементу (целочисленное значение) [дубликаты]

331

На этот вопрос уже есть ответ:

Как отсортировать (список / кортеж) списки / кортежи? 10 ответов

У меня есть список кортежей, который выглядит примерно так:

[('abc', 121),('abc', 231),('abc', 148), ('abc',221)]

Я хочу отсортировать этот список в порядке возрастания по целочисленному значению внутри кортежей. Является ли это возможным

Ваш Ответ

9   ответов
3

ДляPython 2.7+, это работает, что делает принятый ответ немного более читабельным:

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda (k, val): val)
7

цию:

def MyFn(a):
    return a[1]

тогда

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=MyFn)
Каковы преимущества этого? dromtrund
Одним из преимуществ было бы наличие определенной функции, которую вы могли бы использовать где угодно без необходимости ставитьlambda x: x[1] в нескольких областях кода. Tom Myddeltyn
Еще одно преимущество заключается в том, что вы можете лучше документировать / комментировать, если это отдельная функция. uli42
37

я просто хотел упомянуть, что если данные действительно выглядят так:

data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]

тогдаsorted() автоматически сортирует по второму элементу в кортеже, так как все первые элементы идентичн

Хорошее наблюдение и замечание. SKR
509

Попробуйте с помощьюkey ключевое слово сsorted().

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)], key=lambda x: x[1])

key должна быть функцией, которая определяет, как извлечь сопоставимый элемент из вашей структуры данных. В вашем случае это второй элемент кортежа, поэтому мы обращаемся к[1].

Для оптимизации смотрите ответ Джеймилака, используяitemgetter(1), которая по сути является более быстрой версиейlambda x: x[1].

Пока очевидно. Sorted не сортирует по месту, поэтому: sorted_list = sorted ([('abc', 121), ('abc', 231), ('abc', 148), ('abc', 221)], ключ = лямбда x : x [1]) Vesanto
, reverse = True для самых больших и самых маленьких. jonincanada
Это все еще хорошо работает с Python 3.7. jftuga
Вы также можете добавить несколько ключей в виде кортежа, если вы хотите, чтобы один из них был перевернутым, вы можете добавить отрицательный знак, это отсортирует сначала по первому элементу, а затем по второму:sorted(some_list, lambda x: (x[0], -x[1],)) Seraf
9

Для сортировки на месте используйте

foo = [(list of tuples)]
foo.sort(key=lambda x:x[0]) #To sort by first element of the tuple
Хотя этот ответ может быть правильным, лучше объяснить, почему он правильный, а не только код. Кроме того, это почти точный ответ того, который уже существует и был принят 5 лет назад, так что это ничего не добавляет к сайту. Посмотрите на новые вопросы, чтобы помочь людям! JNYRanger
на самом деле это помогает людям, ищущим сортировку на месте leoschet
Хотя это полезно, скорее всего, это будет более уместно в качестве комментария к предлагаемому ответу, показывающего, как можно использовать тот же метод, что и в этом ответе, для выполнения той же задачи на месте. Michael DiStefano
14

Из питона вики:

>>> from operator import itemgetter, attrgetter    
>>> sorted(student_tuples, key=itemgetter(2))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]    
>>> sorted(student_objects, key=attrgetter('age'))
[('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
x = [[[5,3], 1.0345], [[5,6], 5.098], [[5,4], 4.89], [[5,1], 5.97]] С таким списком мы можем отсортировать, используя itemgetter () по элементам в x [0] [1]? nidHi
179
>>> from operator import itemgetter
>>> data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]
>>> sorted(data,key=itemgetter(1))
[('abc', 121), ('abc', 148), ('abc', 221), ('abc', 231)]

IMO используяitemgetter этом случае @ читается лучше, чем решение @cheeken. Это также быстрее, так как почти все вычисления будут выполняться наc side (без каламбура), а не черезlambda.

>python -m timeit -s "from operator import itemgetter; data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=itemgetter(1))"
1000000 loops, best of 3: 1.22 usec per loop

>python -m timeit -s "data = [('abc', 121),('abc', 231),('abc', 148), ('abc',221)]" "sorted(data,key=lambda x: x[1])"
1000000 loops, best of 3: 1.4 usec per loop
+ 1 Я согласен, чтоitemgetter() - лучшее решение. Тем не менее, я думал, что лямбда-выражение прояснит, какkey функции. cheeken
+ 1 Однако, когда я провел тестирование скорости, я заметил «человеческий глаз», что тот, который должен быть быстрее ... и измерен быстрее, на самом деле был заметно медленнее. Я немного почесал голову над этим, затем вывел из строя модуль времени ожидания Python и просто использовал время Linux. то естьtime `python -c "the code"` тогда я получил результаты «человеческого глаза», которые вы излагали, а также системные часы, которые были быстрее. До сих пор не уверен, почему это так, но это было воспроизводимо. Я полагаю, это как-то связано с накладными расходами на загрузку в модуле, но до сих пор не совсем, так как для меня, пок Jeff Sheffield
@ JeffSheffield: обратите внимание, что jamylak выполняет импорт в коде установки (вне времени), а не в проверенном коде. Это совершенно разумно, потому что большинству программ потребуется сортировка более одного раза или сортировка намного больших коллекций, но они будут выполнять импорт только один раз. (И для тех программ, которые должны выполнять только одну небольшую сортировку ... ну, вы говорите о разнице в микросекундах, так кого это волнует в любом случае?) abarnert
@ abarnert FYI: jamylak делает импорт внутриpython -m timeit -s но да, я думаю, вы намерены сказать, что в производственном сценарии вы платите штраф за загрузку только один раз. и ... что касается того, кому небезразлична эта микросекунда ... вас волнует, поскольку предполагается, что ваши данные сортировки станут достаточно большими, и эта микросекунда превратится в реальные секунды, когда набор данных увеличится. Jeff Sheffield
@ JeffSheffield: В том-то и дело: стоимость импорта не будет расти вместе с данными, поэтому даже если кажется, что большая часть 1us, которую вы платите за один маленький размер, будет неактуальной частью 500 мс, которые вы платите за большой сорт или кучу мелких. abarnert
0

что значения сортировки в ОП являются целыми числами, сам по себе не относится к данному вопросу. Другими словами, принятый ответ будет работать, если значение сортировки будет текстовым. Я привожу это, чтобы также указать, что сортировка может быть изменена во время сортировки (например, для учета верхнего и нижнего регистра).

>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: x[1])
[(148, 'ABC'), (221, 'DEF'), (121, 'abc'), (231, 'def')]
>>> sorted([(121, 'abc'), (231, 'def'), (148, 'ABC'), (221, 'DEF')], key=lambda x: str.lower(x[1]))
[(121, 'abc'), (148, 'ABC'), (231, 'def'), (221, 'DEF')]
36

-му элементу вв порядке убывани.

sorted([('abc', 121),('abc', 231),('abc', 148), ('abc',221)],key=lambda x: x[1], reverse=True)

Похожие вопросы