Как сгруппировать список кортежей / объектов по аналогичному индексу / атрибуту в python? - PullRequest
28 голосов
/ 06 июля 2011

Дан список

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 проверок вместе, но это ужасно. Есть ли для этого питонский путь? Кстати, все атрибуты объектов - это строки.

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

Ответы [ 3 ]

42 голосов
/ 07 июля 2011

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()
23 голосов
/ 07 июля 2011

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

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 как ответ С. Лотта, но не обязательно использовать 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))
12 голосов
/ 07 июля 2011

Думаю, вы также можете попробовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...