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

Python 计算部分列表出现次数的最快方法,python,python-3.x,list,performance,Python,Python 3.x,List,Performance,从开始位置到停止位置,计算图元出现次数的最快方法是什么 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:endpo

从开始位置到停止位置,计算图元出现次数的最快方法是什么

 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)
但是,这看起来仍然比第一个选项慢,并且将复制列表的很大一部分

由于字符串有这样一个count函数,我们可以将列表连接到一个字符串,然后使用内置的count函数,但是由于列表很大,转换为字符串似乎不是一种更快的方法

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

试试这个:

from collections import Counter
print(Counter(my_list[start:end]))
如果愿意,您可以将
计数器
对象转换为dict:

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

from collections import Counter
print(Counter(my_list[start:end]))
如果愿意,您可以将
计数器
对象转换为dict:

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

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

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
是否在
范围内是快速的

展开循环将有助于休息-如果快速性非常关键,你应该计时你的方法:

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
maxpos=max(pos)
最小位置=最小(位置)
对于idx,枚举(d)中的元素:
如果idxpos:
打破
#查一查元素,数一数
持续

如果您只测试列表中的一小部分,这可能会更快,也可能不会更快。如果您测试列表中的最后一个元素,这不会有多大作用,但是如果您的列表很大,并且您的目标区域是“最前面”的,则中断可能会为您节省一些周期

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

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
是否在
范围内是快速的

展开循环将有助于休息-如果快速性非常关键,你应该计时你的方法:

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
maxpos=max(pos)
最小位置=最小(位置)
对于idx,枚举(d)中的元素:
如果idxpos:
打破
#查一查元素,数一数
持续

如果您只测试列表中的一小部分,这可能会更快,也可能不会更快。如果您测试列表中的最后一个元素,这不会有多大作用,但是如果您的列表很大,并且您的目标区域是“最前面”的话,如果您想要一个纯Python解决方案,中断可能会为您节省一些周期,将第一个选项转换为
sum
函数中的生成器表达式可能是非常大的列表的最有效解决方案:

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))

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

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))

lst[start:end].count(elem)
enumerate
版本更好更快(几乎是10倍,但我想这取决于范围),但您的替代方案与
list[start:end].count一样,没有额外的空间。“更好更快”取决于您提供的数据。如果在5.2个数据点的子列表中有50亿个数据点,那么复制这50亿个数据点并随后计数可能比迭代它们的成本更高-这就是为什么我提到了
timeit
-ing它。为了便于阅读和良好的C++实现,复制.CONTUTE()变量可能是我要进行的99/100次。问题的前提是一个很长的列表,因此,如果所需的范围接近列表的末尾,那么从列表的开头进行迭代可能会非常低效,因为循环会浪费在范围之外的迭代中。完全同意。当数据非常大的时候。我会使用您提到的第二种方法,或者首先使用NumPy数组来处理如此大的数据。@blh您使用生成器和的方式更好:)
lst[start:end]。count(elem)
enumerate
version更好更快(几乎是10倍,但我想这取决于范围)但是,您的替代方案与
列表[start:end].count相同,没有额外的空间。“更好更快”取决于您提供的数据。如果在5.2个数据点的子列表中有50亿个数据点,那么复制这50亿个数据点并随后计数可能比迭代它们的成本更高-这就是为什么我提到了
timeit
-ing它。为了便于阅读和良好的C++实现,复制.CONTUTE()变量可能是我要进行的99/100次。问题的前提是一个很长的列表,因此,如果所需的范围接近列表的末尾,那么从列表的开头进行迭代可能会非常低效,因为循环会浪费在范围之外的迭代中。完全同意。当数据非常大的时候。我会的