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

给出一个列表

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

我想创build一个列表:

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

其中obj_1.some_attr == obj_2.some_attr

我可以扔一些循环, if一起检查,但这是丑陋的。 有没有pythonic的方式呢? 顺便说一下,对象的属性都是string。

或者,也可以使用包含元组(长度相同)而不是对象的列表解决scheme。

defaultdict是这样做的。

while循环在很大程度上是必不可less的, if语句不是。

 from collections import defaultdict groups = defaultdict(list) for obj in old_list: groups[obj.some_attr].append(obj) new_list = groups.values() 

这里有两种情况。 两者都需要以下导入:

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

请注意,您需要sorting,因为当键值发生更改时, itertools.groupby会创build一个新组。


请注意,您可以使用这个来创build一个dict如S.Lott的答案,但不必使用collections.defaultdict

使用字典理解(只适用于Python 3 +,可能Python 2.7,但我不知道):

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

对于以前的Python版本,或者作为更简洁的select:

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

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