如何在python中按类似的索引/属性对元组/对象列表进行分组?

时间:2011-07-06 19:59:01

标签: python list grouping

给出一个清单

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检查放在一起,但这很难看。这有什么pythonic方式吗?顺便说一句,对象的属性都是字符串。

另外,对于包含元组(长度相同)而不是对象的列表的解决方案也是如此。

3 个答案:

答案 0 :(得分:40)

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()

答案 1 :(得分:23)

这是两个案例。两者都需要以下导入:

import itertools
import operator

您将使用itertools.groupby以及operator.attrgetteroperator.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))

答案 2 :(得分:12)

认为您也可以尝试使用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