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

Auf*_*ind 31 python grouping list

给出一个清单

old_list = [obj_1, obj_2, obj_3, ...]
Run Code Online (Sandbox Code Playgroud)

我想创建一个列表:

new_list = [[obj_1, obj_2], [obj_3], ...]
Run Code Online (Sandbox Code Playgroud)

哪里obj_1.some_attr == obj_2.some_attr.

我可以把一些for循环和if检查放在一起,但这很难看.这有什么pythonic方式吗?顺便说一句,对象的属性都是字符串.

或者,也可以理解包含元组(具有相同长度)而不是对象的列表的解决方案.

S.L*_*ott 45

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()
Run Code Online (Sandbox Code Playgroud)

  • 当然,这并不保留(或以任何方式尊重)组的原始顺序.所以它可能是也可能不是@Druss想要的. (3认同)
  • 难道不应该调用“list(groups.values())”来实际返回OP想要的内容吗?我的意思是,否则,如果有人调用“new_list[0]”,她会得到“TypeError:'dict_values'对象不支持索引”(至少在我的机器上)。 (3认同)
  • @jollybox.de:“不保留(或以任何方式尊重)组的原始顺序”正确。什么时候这成为一个要求? (2认同)

JAB*_*JAB 25

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

import itertools
import operator
Run Code Online (Sandbox Code Playgroud)

您将使用itertools.groupbyoperator.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)]
Run Code Online (Sandbox Code Playgroud)

用于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)]
Run Code Online (Sandbox Code Playgroud)

请注意,您需要排序,因为itertools.groupby当键的值更改时创建一个新组.


请注意,您可以使用它来创建dict类似S.Lott的答案,但不必使用collections.defaultdict.

使用字典理解(仅适用于Python 3+,可能还适用于Python 2.7,但我不确定):

groupdict = {k: g for k, g in itertools.groupby(sorted_list, keyfunction)}
Run Code Online (Sandbox Code Playgroud)

对于以前版本的Python,或者作为更简洁的替代方案:

groupdict = dict(itertools.groupby(sorted_list, keyfunction))
Run Code Online (Sandbox Code Playgroud)


Art*_*nka 14

认为你也可以尝试使用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
Run Code Online (Sandbox Code Playgroud)

  • @JAB-你的真相。谢谢你注意到我。 (2认同)
  • @SahilChhabra阅读我的回答,我说为什么。 (2认同)