Python在列表中计数事件:如何使其更快?

Python在列表中计数事件:如何使其更快?,python,performance,list,counting,Python,Performance,List,Counting,我有一个字符串列表,其中包含大约600万项,我正在尝试计算每个唯一值的出现次数 这是我的密码: lines = [6 million strings] unique_val = list(set(lines)) # contains around 500k items mydict = {} for val in unique_val: mydict[val] = lines.count(val) 我发现上面的代码非常慢,因为我正在计算的列表非常大 我想知道是否有办法使它更快

我有一个字符串列表,其中包含大约600万项,我正在尝试计算每个唯一值的出现次数

这是我的密码:

lines = [6 million strings]
unique_val = list(set(lines))    # contains around 500k items

mydict = {}
for val in unique_val:
    mydict[val] = lines.count(val)
我发现上面的代码非常慢,因为我正在计算的列表非常大

我想知道是否有办法使它更快


如果您不想使用
收藏
模块,非常感谢

counts = dict()
for line in lines:
    counts[line] = counts.get(line,0) + 1
或者如果您只是不想使用
计数器

from collection import defaultdict
counts = defaultdict(int)
for line in lines:
    counts[line] += 1

如果您不想使用
集合
模块

counts = dict()
for line in lines:
    counts[line] = counts.get(line,0) + 1
或者如果您只是不想使用
计数器

from collection import defaultdict
counts = defaultdict(int)
for line in lines:
    counts[line] += 1
这个怎么样,

from collections import defaultdict
import collections

lines = [600 million strings]

d = defaultdict(int)
for line in lines:
    for word, count in collections.Counter(line).items():
        d[word] += count
这个怎么样,

from collections import defaultdict
import collections

lines = [600 million strings]

d = defaultdict(int)
for line in lines:
    for word, count in collections.Counter(line).items():
        d[word] += count

Numpy解决方案

我认为numpy将通过以下方式为您提供最快的答案:

Numpy在引擎盖下进行了大量优化。根据链接的文档,围绕
return\u计数的魔法圆圈
标志:

返回计数
:布尔,可选

如果为真,还返回ar中每个唯一值出现的次数


定时

我给你最初的方法计时,反方法

result = Counter(lines)
以及由

N = 1000000
lines = [chr(i%100) for i in range(N) ]
显然,这项测试覆盖率不高,但这只是一个开始


你的进近操作在0.584s;深度空间的计数器为0.162(3.5倍加速比),而numpy的计数器为0.0861(7倍加速比)。同样,这可能取决于许多因素,包括您拥有的数据类型:结论可能是numpy或计数器将提供加速,计数器不需要外部库

numpy解决方案

我认为numpy将通过以下方式为您提供最快的答案:

Numpy在引擎盖下进行了大量优化。根据链接的文档,围绕
return\u计数的魔法圆圈
标志:

返回计数
:布尔,可选

如果为True,还返回每个唯一值在ar中出现的次数


定时

我给你最初的方法计时,反方法

result = Counter(lines)
以及由

N = 1000000
lines = [chr(i%100) for i in range(N) ]
显然,这项测试覆盖率不高,但这只是一个开始


你的进近操作在0.584s;深度空间的计数器为0.162(3.5倍加速比),而numpy的计数器为0.0861(7倍加速比)。同样,这可能取决于许多因素,包括您拥有的数据类型:结论可能是numpy或计数器将提供加速,计数器不需要外部库调用
列表。计数非常昂贵。字典访问(O(1)摊销时间)和
中的
操作符相对便宜。下面的代码片段显示了更好的时间复杂性

def stats(lines):
    histogram = {}
    for s in lines:
        if s in histogram:
            histogram[s] += 1
        else:
            histogram[s] = 1
    return histogram

调用
list.count
非常昂贵。字典访问(O(1)摊销时间)和
中的
操作符相对便宜。下面的代码片段显示了更好的时间复杂性

def stats(lines):
    histogram = {}
    for s in lines:
        if s in histogram:
            histogram[s] += 1
        else:
            histogram[s] = 1
    return histogram


这可能对于
pyspark
来说足够大,并且非常适合这种类型的问题。您是否愿意使用非纯python软件包(如numpy或pyspark?)。此外,我使用右大括号编辑了您的代码,以使其正常运行-我知道编辑代码通常是不受欢迎的(这似乎是一个非常明显的打字错误),但是,如果出于某种原因您指的是原始版本,请回滚editsDo,以便从外部文件读取数据?如果是这样,我建议逐行迭代,而不是一次加载到内存中。这可能对于
pyspark
来说足够大,并且非常适合这种类型的问题。您是否愿意使用非纯python软件包(如numpy或pyspark?),我用右大括号编辑了你的代码,这样它就可以正常运行了。我知道编辑代码通常是不受欢迎的(这似乎是一个非常明显的打字错误),但是如果你出于某种原因是指原始代码,请回滚编辑器,以便从外部文件读取数据?如果是这样的话,我建议逐行迭代,而不是一次加载到内存中。为什么你要在DeepSpace上这样做,而他的结果似乎更简洁?(当然,我认为他不应该被要求加入他的团队)@en_Knight,谢谢你指出这一点。我刚刚编辑了我的答案。嗯,我仍然不明白这怎么比
d=计数器(行)
更好。为什么我们要循环,多次调用计数器,复制字典?你可能正在进行内存优化吗?@en_Knight,如果OP将数据存储在一个外部文件中,那么逐行迭代读取数据将非常有帮助,而不是一次加载到内存中。为什么你要在DeepSpace上这样做,而他的结果似乎更简洁?(当然,我认为他不应该被要求加入他的团队)@en_Knight,谢谢你指出这一点。我刚刚编辑了我的答案。嗯,我仍然不明白这怎么比
d=计数器(行)
更好。为什么我们要循环,多次调用计数器,复制字典?您可能正在进行内存优化吗?@en_Knight,如果OP将数据存储在外部文件中,那么逐行迭代读取数据将非常有帮助,而不是一次加载到内存中。嗨,michael,第一个是如何工作的?看起来计数没有初始化为任何值,所以我看不出它是如何更新的?(当我运行它时,它似乎也不工作…)。“get”函数查找一个键,如果该键不存在,则返回0,但由于我们从未添加任何键,它是否总是0?@en_Knight,:)显然不起作用。最后我错过了
+1
。我现在已经编辑好了嗨,迈克尔,第一个是怎么工作的?看起来计数没有初始化为任何值,所以我看不出它是如何更新的?(当我运行它时,它似乎也不工作…)。“get”函数查找一个键,如果该键不在那里,则返回0,但因为我们从未