Python 按属性将列表划分为子列表

Python 按属性将列表划分为子列表,python,Python,我有以下分区功能: def group_by_name(data): names = set([entry.name for entry in data]) # detect all possible names # and now create a sublist for each possible name by_name = [[entry for entry in data if entry.name == name] for name in names]

我有以下分区功能:

def group_by_name(data):
    names = set([entry.name for entry in data])  # detect all possible names
    # and now create a sublist for each possible name
    by_name = [[entry for entry in data if entry.name == name] for name in names]
    return by_name
是否有一种更具python风格的方法来实现此功能

编辑 数据:

import random


class Data:
    def __init__(self, name):
        self.name = name

NAMES = [ 'jose', 'pedro', 'antonio', 'jesus', 'ricardo', 'anabel']

data = [Data(random.choice(NAMES)) for _ in range(100)]
您的方法是
O(N*K)
,因为您迭代整个列表的次数与不同元素的次数相同。您可以使用以下模式在一次迭代中收集列表(
O(N)
):

def group_by_name(data):
    d = {}
    for entry in data:
        d.setdefault(entry.name, []).append(entry)
    return list(d.values())
您还可以使用一些util使用一个
O(N*logN)
1行程序:

from operator import attrgetter as ag
from itertools import groupby as gb

def group_by_name(data): 
    return [list(g) for _, g in gb(sorted(data, key=ag('name')), key=ag('name'))]

使用字典并在数据上循环,使用名称作为键,使用条目列表作为值。然后将每个键的值放入新构造的列表中,然后返回它。因为这是线性运行时,所以效率更高。

一个可共享的
数据实例就更好了。此外,根据其类型可能会有一些技巧。@Kanak数据添加
setdefault
将大大简化我的代码!我以前做过
if key not in d
来初始化dicts…您也可以使用
collections.defaultdict
来进一步提高可读性:
d=defaultdict(list)
并且在循环中只需
d[entry.name].append(entry)
defaultdict
不是比
dict
慢很多吗?如果您注意到一个很大的差异,我会感到惊讶。毕竟,它是dict的子类,在大多数操作中有效地使用相同的C代码。我要说的是,在几乎所有现实世界的情况下,可读性以及因此产生的生产力/可维护性都胜过性能。@NiklasMertsch“在一次迭代中收集列表”,这是正确的。返回值的列表构造函数不会迭代
数据
,而是迭代
d
O(k)
,如果愿意的话),它会呈现整个过程
O(n+k)