暂时不考虑你的代码问题,我想指出常用且最快的计数方法之一是使用collections模块中的Counter类。以下是Python 2.7.3解释器中使用它的示例:
>>> from collections import Counter
>>> lets=Counter('aaaaabadfasdfasdfafsdff')
>>> lets
Counter({'a': 9, 'f': 6, 'd': 4, 's': 3, 'b': 1})
>>> s = "the quick brown fox jumped over the lazy dog"
>>> Counter(s)
Counter({' ': 8, 'e': 4, 'o': 4, 'd': 2, 'h': 2, 'r': 2, 'u': 2, 't': 2, 'a': 1, 'c': 1, 'b': 1, 'g': 1, 'f': 1, 'i': 1, 'k': 1, 'j': 1, 'm': 1, 'l': 1, 'n': 1, 'q': 1, 'p': 1, 'w': 1, 'v': 1, 'y': 1, 'x': 1, 'z': 1})
使用reduce,定义一个辅助函数addto(oldtotal,newitem)
,将newitem
添加到oldtotal
并返回一个新的总数。总数的初始化器是一个空字典{}
。这是一个解释性的例子。请注意,get()的第二个参数是当键尚未在字典中时要使用的默认值。
>>> def addto(d,x):
... d[x] = d.get(x,0) + 1
... return d
...
>>> reduce (addto, s, {})
{' ': 8, 'a': 1, 'c': 1, 'b': 1, 'e': 4, 'd': 2, 'g': 1, 'f': 1, 'i': 1, 'h': 2, 'k': 1, 'j': 1, 'm': 1, 'l': 1, 'o': 4, 'n': 1, 'q': 1, 'p': 1, 'r': 2, 'u': 2, 't': 2, 'w': 1, 'v': 1, 'y': 1, 'x': 1, 'z': 1}
下面显示的代码打印了多个方法每次执行1000次的执行时间。在旧的AMD Athlon 5000+ Linux 3.2.0-32 Ubuntu 12系统上执行时,使用两个不同的字符串s
,它打印出:
String length is 44 Pass count is 1000
horsch1 : 0.77517914772
horsch2 : 0.778718948364
jreduce : 0.0403778553009
jcounter: 0.0699260234833
String length is 4931 Pass count is 100
horsch1 : 8.25176692009
horsch2 : 8.14318394661
jreduce : 0.260674953461
jcounter: 0.282369852066
(reduce方法比Counter方法稍微快一些。)以下是计时代码,它使用timeit模块。在这里的代码中,timeit.Timer
的第一个参数是要重复计时的代码,第二个参数是设置代码。
import timeit
from collections import Counter
passes = 1000
m1 = lambda x: [int(ord(x) == i) for i in xrange(65,91)]
def m2(x):
return [int(ord(x) == i) for i in xrange(65,91)]
def es1(s):
add = lambda x,y: [x[i]+y[i] for i in xrange(len(x))]
freq = reduce(add,map(m1, s.upper()))
return freq
def es2(s):
add = lambda x,y: [x[i]+y[i] for i in xrange(len(x))]
freq = reduce(add,map(m2, s.upper()))
return freq
def addto(d,x):
d[x] = d.get(x,0) + 1
return d
def jwc(s):
return Counter(s)
def jwr(s):
return reduce (addto, s, {})
s = "the quick brown fox jumped over the lazy dog"
print 'String length is',len(s), ' Pass count is',passes
print "horsch1 :",timeit.Timer('f(s)', 'from __main__ import s, m1, es1 as f').timeit(passes)
print "horsch2 :",timeit.Timer('f(s)', 'from __main__ import s, m2, es2 as f').timeit(passes)
print "jreduce :",timeit.Timer('f(s)', 'from __main__ import s, addto, jwr as f').timeit(passes)
print "jcounter:",timeit.Timer('f(s)', 'from __main__ import s, Counter,jwc as f').timeit(passes)