Подтвердить что ты не робот

Как сгруппировать список кортежей/объектов с помощью аналогичного индекса/атрибута в python?

Учитывая список

old_list = [obj_1, obj_2, obj_3, ...]

Я хочу создать список:

new_list = [[obj_1, obj_2], [obj_3], ...]

где obj_1.some_attr == obj_2.some_attr.

Я мог бы пропустить несколько циклов for и if, но это уродливо. Есть ли для этого питонический способ? Кстати, атрибутами объектов являются все строки.

Кроме того, также рекомендуется решение для списка, содержащего кортежи (одинаковой длины) вместо объектов.

4b9b3361

Ответ 1

defaultdict, как это делается.

Хотя циклы for во многом важны, операторы if не являются.

from collections import defaultdict


groups = defaultdict(list)

for obj in old_list:
    groups[obj.some_attr].append(obj)

new_list = groups.values()

Ответ 2

Вот два случая. Оба требуют следующий импорт:

import itertools
import operator

Вы будете использовать itertools.groupby и operator.attrgetter или operator.itemgetter.

В ситуации, когда вы группируете obj_1.some_attr == obj_2.some_attr:

get_attr = operator.attrgetter('some_attr')
new_list = [list(g) for k, g in itertools.groupby(sorted(old_list, key=get_attr), get_attr)]

Для a[some_index] == b[some_index]:

get_item = operator.itemgetter(some_index)
new_list = [list(g) for k, g in itertools.groupby(sorted(old_list, key=get_item), get_item)]

Обратите внимание, что вам нужна сортировка, потому что itertools.groupby создает новую группу, когда изменяется значение ключа.


Обратите внимание, что вы можете использовать это для создания dict как ответ S.Lott, но не нужно использовать collections.defaultdict.

Использование понимания словаря (работает только с Python 3+ и, возможно, с Python 2.7, но я не уверен):

groupdict = {k: g for k, g in itertools.groupby(sorted_list, keyfunction)}

Для предыдущих версий Python или в качестве более сжатой альтернативы:

groupdict = dict(itertools.groupby(sorted_list, keyfunction))

Ответ 3

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

data = [[1,2,3],[3,2,3],[1,1,1],[7,8,9],[7,7,9]]

from itertools import groupby

# for example if you need to get data grouped by each third element you can use the following code
res = [list(v) for l,v in groupby(sorted(data, key=lambda x:x[2]), lambda x: x[2])]# use third element for grouping