python - 为什么 itertools.groupby() 比使用 defaultdict 的等效方法慢得多?

标签 python performance

我想检查 groupby() 和基于 defaultdict 的自定义配方对数据进行分组哪个更快:

from collections import defaultdict
from itertools import groupby

def g1(data):
    groupdict = defaultdict(list)
    for value in data:
        group = value[0]
        value = value[1]
        groupdict[group].append(value)
    return [(key, ''.join(values)) for key, values in groupdict.items()]

def g2(data):
    extractKey = lambda x: x[0]
    aggregate = lambda g: ''.join(x[1] for x in g)
    #return [(k, aggregate(g)) for k, g in groupby(data, extractKey)]
    return [(k, aggregate(g)) for k, g in groupby(sorted(data, key=extractKey), extractKey)]

import random

keys = list(range(1,100))
vals = 'abcdefghijklmnopqrstuvwxyz'

data = [(random.choice(keys), random.choice(vals)) for _ in range(1000)]
#data.sort()

import timeit

for g in ('g1', 'g2'):
    print(g, timeit.timeit(g + '(data)', number=1000, globals=globals()))

令我惊讶的是,groupby() 几乎比 defaultdict 慢 3 倍。

g1 0.17048488299769815

g2 0.47328821099654306

即使数据已预先排序,即我们也不计算 sort()ing 所花费的时间(取消注释两行注释),其中应该groupby() 应该比其他配方更快执行,但速度慢了近 1.5 倍。

g1 0.17607520399906207

g2 0.2464493800071068

为什么? g2 中是否有一些我忽略的优化?

最佳答案

与仅索引元组相比,这与 lambda 调用的开销有关。

如果您重写第一个案例以使用 extractKey:

def g1(data):
    groupdict = defaultdict(list)
    extractKey = lambda x: x[0]
    for value in data:
        group = extractKey(value)
        value = value[1]
        groupdict[group].append(value)
    return [(key, ''.join(values)) for key, values in groupdict.items()]

那么它们的速度几乎相同(在非排序情况下)。

关于python - 为什么 itertools.groupby() 比使用 defaultdict 的等效方法慢得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50087315/

相关文章:

android - 如何提高 Android 应用程序的整体性能?

javascript - 如何衡量单页应用程序中的客户端性能

performance - 如何获得 Intel Xeon E5-2690 GFlop/s 的峰值性能?

python - Pandas 根据另一列条件下的值的随机样本替换 NaN 值

python - 我可以让我的 pip 用户安装包优先于系统吗?

python - scrapy抓取多个页面,提取数据并保存到mysql中

具有列表理解的Python字典值分配

performance - CentOS CPU 使用率

php - file_exists() 在 PHP 中太慢了。任何人都可以提出更快的替代方案吗?

Python PyGO对象 TreeView : confirm edit after move between cells with Tab key