Сортировка и группировка вложенных списков в Python

У меня следующая структура данных (список списков)

[
 ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
 ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
 ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
 ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
]

Я хотел бы иметь возможность

  1. Используйте функцию, чтобы изменить порядок списка, чтобы я мог группировать по каждому элементу в списке. Например, я хотел бы иметь возможность группировать по второму столбцу (чтобы все 21 были вместе)

  2. Используйте функцию, чтобы отображать только определенные значения из каждого внутреннего списка. Например, я хотел бы сократить этот список, чтобы он содержал только 4-е значение поля «2somename».

так что список будет выглядеть так

[
     ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
     ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
]

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

user3850 04.01.2009 03:26
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
49
1
74 295
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Если я правильно понимаю ваш вопрос, следующий код должен сработать:

l = [
 ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
 ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
 ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
 ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
]

def compareField(field):
   def c(l1,l2):
      return cmp(l1[field], l2[field])
   return c

# Use compareField(1) as the ordering criterion, i.e. sort only with
# respect to the 2nd field
l.sort(compareField(1))
for row in l: print row

print
# Select only those sublists for which 4th field=='2somename'
l2somename = [row for row in l if row[3]=='2somename']
for row in l2somename: print row

Выход:

['4', '21', '1', '14', '2008-10-24 15:42:58']
['5', '21', '3', '19', '2008-10-24 15:45:45']
['6', '21', '1', '1somename', '2008-10-24 15:45:49']
['3', '22', '4', '2somename', '2008-10-24 15:22:03']
['7', '22', '3', '2somename', '2008-10-24 15:45:51']

['3', '22', '4', '2somename', '2008-10-24 15:22:03']
['7', '22', '3', '2somename', '2008-10-24 15:45:51']

Аргумент 'cmp' для сортировки удален в 2.6 / 3.0, поэтому предпочтительнее использовать параметр 'key', который извлекает ключ сортировки, но в противном случае +1.

Aaron Maenpaa 03.01.2009 20:29

удален 'cmp =', в любом случае должен быть первым аргументом. Кстати, я использую python 2.6.1, и все работает нормально ...

Federico A. Ramponi 03.01.2009 20:36

Если вы присвоили его переменной "a" ...

Python 2.x:

№1:

a.sort(lambda x,y: cmp(x[1], y[1]))

# 2:

filter(lambda x: x[3]= = "2somename", a)

питон 3:

№1:

a.sort(key=lambda x: x[1])

Более простой и понятный подход, чем itemgetter

Hamman Samuel 30.06.2016 12:18

лямбда для победы. Мне очень понравилось это решение

alfredocambera 10.11.2016 22:31

Use a function to reorder the list so that I can group by each item in the list. For example I'd like to be able to group by the second column (so that all the 21's are together)

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

>>> import pprint
>>> l.sort(key = lambda ll: ll[1])
>>> pprint.pprint(l)
[['4', '21', '1', '14', '2008-10-24 15:42:58'],
 ['5', '21', '3', '19', '2008-10-24 15:45:45'],
 ['6', '21', '1', '1somename', '2008-10-24 15:45:49'],
 ['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]

Use a function to only display certain values from each inner list. For example i'd like to reduce this list to only contain the 4th field value of '2somename'

Похоже, это работа для составить список

>>> [ll[3] for ll in l]
['14', '2somename', '19', '1somename', '2somename']

Замените [ll[3] for ll in l] на [ll for ll in l if ll[3] == '2somename'] и исправьте вывод.

jfs 03.01.2009 21:39
Ответ принят как подходящий

Что касается первого вопроса, первое, что вам следует сделать, это отсортировать список по второму полю, используя itemgetter из модуля оператора:

x = [
 ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
 ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
 ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
 ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
]

from operator import itemgetter

x.sort(key=itemgetter(1))

Затем вы можете использовать функцию группа по itertools:

from itertools import groupby
y = groupby(x, itemgetter(1))

Теперь y - итератор, содержащий кортежи (element, item iterator). Объяснять эти кортежи сложнее, чем показывать код:

for elt, items in groupby(x, itemgetter(1)):
    print(elt, items)
    for i in items:
        print(i)

Какие отпечатки:

21 <itertools._grouper object at 0x511a0>
['4', '21', '1', '14', '2008-10-24 15:42:58']
['5', '21', '3', '19', '2008-10-24 15:45:45']
['6', '21', '1', '1somename', '2008-10-24 15:45:49']
22 <itertools._grouper object at 0x51170>
['3', '22', '4', '2somename', '2008-10-24 15:22:03']
['7', '22', '3', '2somename', '2008-10-24 15:45:51']

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

from pprint import pprint as pp
pp([y for y in x if y[3] == '2somename'])

Какие отпечатки:

[['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]

Я добавил пример понимания списка.

jfs 03.01.2009 21:34

Этот ответ был написан давно, и в настоящее время вы должны использовать выражение генератора вместо понимания списка: pp(y for y in x if y[3] == '2somename')

llimllib 25.06.2017 23:17

нет. Это неверно. genexpr здесь не подходит. Попробуйте запустить код.

jfs 25.06.2017 23:22

Если вы будете много заниматься сортировкой и фильтрацией, вам могут понравиться некоторые вспомогательные функции.

m = [
 ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
 ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
 ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
 ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
 ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
]

# Sort and filter helpers.
sort_on   = lambda pos:     lambda x: x[pos]
filter_on = lambda pos,val: lambda l: l[pos] == val

# Sort by second column
m = sorted(m, key=sort_on(1))

# Filter on 4th column, where value = '2somename'
m = filter(filter_on(3,'2somename'),m)

sort_on == operator.itemgetter

jfs 03.01.2009 21:41

Пожалуйста, используйте DEF вместо лямбда-выражений.

S.Lott 03.01.2009 22:33

@ s.lott - почему здесь defs over lambdas?

Triptych 04.01.2009 02:56

@Triptych: потому что лямбда-выражения с именем похожи на defs, но более запутаны и абсолютно бесполезны.

nosklo 05.01.2009 18:01

Мех. В этом случае, я думаю, лямбды более читабельны. И «более запутанное», конечно, субъективно!

Triptych 05.01.2009 18:17

defs здесь будет четыре строки для каждой функции вместо одной.

Thomas Ahle 03.04.2014 10:25

Похоже, вы пытаетесь использовать список в качестве базы данных.

В настоящее время Python включает привязки sqlite в основной дистрибутив. Если вам не нужна настойчивость, действительно легко создать базу данных sqlite в памяти (см. Как создать базу данных sqllite3 в памяти?).

Затем вы можете использовать операторы SQL для выполнения всей этой сортировки и фильтрации, не изобретая велосипед.

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

m3clov3n 03.01.2009 22:16

Что касается части (2), где x - ваш массив, я думаю, вы хотите,

[y for y in x if y[3] == '2somename']

Что вернет список только ваших списков данных, у которых четвертым значением является «2somename» ... Хотя кажется, что Камил дает вам лучший совет по переходу на SQL ...

Вы просто создаете индексы для своей структуры, верно?

>>> from collections import defaultdict
>>> def indexOn( things, pos ):
...     inx= defaultdict(list)
...     for t in things:
...             inx[t[pos]].append(t)
...     return inx
... 
>>> a=[
...  ['4', '21', '1', '14', '2008-10-24 15:42:58'], 
...  ['3', '22', '4', '2somename', '2008-10-24 15:22:03'], 
...  ['5', '21', '3', '19', '2008-10-24 15:45:45'], 
...  ['6', '21', '1', '1somename', '2008-10-24 15:45:49'], 
...  ['7', '22', '3', '2somename', '2008-10-24 15:45:51']
... ]

Вот ваш первый запрос, сгруппированный по позиции 1.

>>> import pprint
>>> pprint.pprint( dict(indexOn(a,1)) )
{'21': [['4', '21', '1', '14', '2008-10-24 15:42:58'],
        ['5', '21', '3', '19', '2008-10-24 15:45:45'],
        ['6', '21', '1', '1somename', '2008-10-24 15:45:49']],
 '22': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
        ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]}

Вот ваш второй запрос, сгруппированный по позиции 3.

>>> dict(indexOn(a,3))
{'19': [['5', '21', '3', '19', '2008-10-24 15:45:45']], '14': [['4', '21', '1', '14', '2008-10-24 15:42:58']], '2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'], ['7', '22', '3', '2somename', '2008-10-24 15:45:51']], '1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']]}
>>> pprint.pprint(_)
{'14': [['4', '21', '1', '14', '2008-10-24 15:42:58']],
 '19': [['5', '21', '3', '19', '2008-10-24 15:45:45']],
 '1somename': [['6', '21', '1', '1somename', '2008-10-24 15:45:49']],
 '2somename': [['3', '22', '4', '2somename', '2008-10-24 15:22:03'],
               ['7', '22', '3', '2somename', '2008-10-24 15:45:51']]} 

Другие вопросы по теме