我有一个列表。它很大,有超过1百万条目。我想计算其中每个字符串的频率。它将数字作为字符串存储从1到1000。我尝试了以下方法,但它运行了几个小时:
d = {b:a.count(b) for b in a}
n, m = d.keys(), d.values()
print n, m
我有一个列表。它很大,有超过1百万条目。我想计算其中每个字符串的频率。它将数字作为字符串存储从1到1000。我尝试了以下方法,但它运行了几个小时:
d = {b:a.count(b) for b in a}
n, m = d.keys(), d.values()
print n, m
collections.Counter
替代:from collections import Counter
d = Counter(a)
n, m = d.keys(), d.values()
print n, m
在这种情况下,使用字典会更加容易。 向字典中插入内容非常快速,从字典中检索数据同样也很快。
以下是一个完全按照此方法操作的示例程序:
import datetime
import random
def create_string(choice, size):
str = ''
for i in range(size):
str = str + random.choice(choice)
return str
def count_all(strings):
count_dict = {}
for i in strings:
if i not in count_dict:
count_dict[i] = 1
else:
count_dict[i] = count_dict[i] + 1
return count_dict
if __name__ == '__main__':
all_strings = []
for i in range(1000000):
all_strings.append(create_string(['a','b','c'], 4))
start = datetime.datetime.now()
c_dict = count_all(all_strings)
end = datetime.datetime.now()
print 'Took:', end - start
print 'The count of aacc is ', c_dict['aacc']
./speed_test.py
Took: 0:00:00.219815
The count of aacc is 12317
还不错,对吧? 作为解决Ant提到的问题的另一种选择,在计数时要消除重复项。我们可以使用一个集合:
d = {b:a.count(b) for b in set(a)}
根据我的测试,这种方法不如使用字典的方法快,但是少于一秒,已经足够好了。
datetime
来分析性能。使用timeit
模块(可以使用iPython),因为它会正确地计算平均时间。如果您想进行单次基准测试,请使用time.perf_counter
,如果您正在使用python3.3+,因为这是它的目的。 - Bakuriu因为你对每个字符串运行了a.count,所以速度很慢!
l = ['a', 'b', 'a']
然后在'a'上调用str.count
两次,在'b'上调用1次。
当然,在'a'上第二次的结果将覆盖字典中的前一个,因此您甚至不会注意到它。
使用默认字典代替。
from collections import defaultdict
d = defaultdict(int)
for obj in your_list:
d[obj] += 1
或者,再次来自collections模块,Counter http://docs.python.org/2/library/collections.html#counter-objects。
dict
,您需要执行n
次(列表a
的长度)成本为n
的操作(a.count(b)
必须遍历所有a
以搜索b
)。这意味着构建它需要与n^2
成比例的时间。如果您有100万条目的列表,则需要执行约(10^6)^2 = 10^12
次操作。即使单个操作是机器指令,构建它也需要大约10^3秒的时间。实际上,每个操作可能需要一些(或至少十几个)机器指令,因此您需要等待数小时/天。 - Bakuriu