1

我正在尝试提高一个函数的性能,该函数计算 Python 中二维数组的一列中某个元素的出现次数。时间来自 cProfile,它也告诉我count()每 357595 次调用仅花费 ~.08 秒。

for 循环最快(357595 次调用为 0.375 秒):

def count_column(grid, j, element):
    count = 0
    for x in range(0, len(grid)):
        if grid[x][j] == element:
            count += 1
    return count

列表推导的速度可以忽略不计(357595 次调用为 0.400 秒):

def count_column(grid, j, element):
    return [x[j] for x in grid].count(element)

Zip 是最慢的,幅度很大(357595 次调用为 0.741 秒):

def validate_column(grid, j, element):
    return zip(*grid)[j].count(element)

有没有更快的方法来做到这一点,或者最好的方法是用 扁平化数组chain.from_iterable

4

2 回答 2

1

这是我得到的一系列不同变化的时间:

cc_explicit 5000 0.00290012359619
cc_explicit_xrange 5000 0.00145506858826
cc_filter 5000 0.00117516517639
cc_genexp 5000 0.00100994110107
cc_ifilter 5000 0.00170707702637
cc_izip 1 3.21103000641
cc_listcomp 5000 0.000788927078247
cc_zip 5000 12.1080589294

代码和测试驱动程序位于http://pastebin.com/WSAUqTyv

由于 zip 和 izip 太慢了,我把它们排除在外,然后用其余的进行 500000x10 测试:

cc_explicit 500000 0.105982065201
cc_explicit_xrange 500000 0.103507995605
cc_filter 500000 0.0856108665466
cc_genexp 500000 0.0679898262024
cc_ifilter 500000 0.144966125488
cc_listcomp 500000 0.0396680831909

因此,最快的解决方案是listcomp. 但是当我向它扔随机数据和更大的行时,有时两者都 beat ,genexp并且它们在大多数测试中都非常接近,并且使用的内存要少得多,所以我会这样做:explicit_xrangelistcompgenexp

def cc_genexp(grid, j, element):
    return sum(x[j] == element for x in grid)
于 2012-12-03T23:22:41.167 回答
0

如果我可以在这里提供我的 2 美分,您还应该查看Numpy,正如已经建议的那样。或者,如果您不想处理非标准库,您应该查看collections.Counter(). 是的,它会带来很大的前期成本,但是如果您发现自己在同一个数据集中计算了许多不同的值,您可能会发现初始投资得到了回报。

于 2012-12-03T23:29:42.873 回答