繁体   English   中英

计算部分列表出现次数的最快方法

[英]fastest way to count occurrences of partial list

从开始 position 到停止 position 计算元素出现的最快方法是什么。

 list = [a,b,c,c,d,c....] can be very long
 count(list,c, from = 2, till = 4) = 2.

我们可以做

 counter = 0
 for i in range(startpos, endpos):
        if symbol == list[i]:
            counter+= 1

或者我们可以做

list[startpos:endpos].count(symbol)

但是,这看起来仍然比第一个选项慢,并且会复制列表的很大一部分

由于字符串有计数 function 像这样,我们可以将列表加入字符串,而不是使用内置计数功能,但是由于列表很大,转换为字符串似乎不是一种更快的方法。

有没有更快的pythonic方法来实现这一点?

如果您想要一个纯 Python 解决方案,将您的第一个选项转换为sum function 中的生成器表达式对于非常大的列表可能是最有效的解决方案:

sum(1 for i in range(startpos, endpos) if list[i] == symbol)

其他选项,例如从列表的开头进行迭代(这会浪费大量时间迭代超出所需范围)或切片(涉及创建副本),当列表非常大时,效率几乎不会那么高。

但是,如果您不介意使用numpy ,则可以创建一个numpy数组而不是列表,这样您就可以在不复制项目的情况下对其进行切片( numpy ,然后在您创建数组时使用sum的方法)计算切片中等于所需值的项目数:

import numpy as np

... # create your very large numpy array as lst

print(np.sum(lst[startpos:endpos] == symbol))

您可以使用生成器和范围来检查枚举索引是否在您的范围内:

a = 2
pos = range(5,15)
d = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,]
total = sum(elem == a for idx,elem in enumerate(d) if idx in pos)

print(total)

这不会复制列表,但会迭代完整的原始列表。 检查idx是否在range很快。

展开循环将允许休息 - 如果紧固度非常关键,您应该安排您的方法:

maxpos = max(pos)
minpos = min(pos)
for idx,elem in enumerate(d):
    if idx < minpos:
        continue
    elif idx > pos:
        break

    # check elem and counts something up
        continue

如果您只测试少量列表,这可能会更快,也可能不会更快 - 如果您使用列表中的最后一个元素,它不会做太多,但如果您的列表很大并且您的目标区域是“前” - 休息可能会为您节省一些周期

试试这个:

from collections import Counter
print(Counter(my_list[start:end]))

如果您愿意,可以将Counter object 转换为 dict:

occurrences = dict(Counter(my_list[start:end]))

只是为了增加 blhsing 的答案,生成器表达式可能稍微不那么冗长:

sum(list[i] == symbol for i in range(startpos, endpos))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM