我编写了几个函数,它们接受一个字符串并返回其中最常用的char。我很想知道实现此目标的最有效方法以及其背后的原因。
出于测试目的,我在Mac上使用Python 3.7.3
。
这就是我所拥有的:
from collections import Counter
def max_char(str):
return Counter(str).most_common(1)[0][0]
def max_char3(str):
return max(str, key=str.count)
def max_char2(str):
counter = 0
max_char = None
max_char_nr = 0
while len(str):
char = str[0]
char_count = str.count(char)
str = str.replace(char, '')
if char_count > max_char_nr:
max_char_nr = char_count
max_char = char
counter += 1
return max_char
def max_char1(str):
chars = {}
for s in str:
if s in chars:
chars[s] += 1
else:
chars[s] = 1
output = ''
max_num = 0
for c in chars:
if chars[c] > max_num:
output = c
max_num = chars[c]
return output
我已经使用timeit
和1000000
迭代对它们进行了测试,其中str='abcdefghijklmnaaaaa'
的迭代结果是:
max_char took: 5.538845853000001
max_char1 took: 2.283595664
max_char2 took: 5.975449033
max_char3 took: 2.9375215150000002
为什么max_char1
的{{1}}复杂度最快(据我了解)。使用O(n+n)
或max_char
中的python内置函数是否应该更高效?
谢谢
EDIT1:添加了测试数据方法的参数
更新1
正如你们中的一些人所建议的,这与我们在例程中传递的数据大小有关。
与
max_char3
我们得到
str='Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry.'
因此,在这一点上,我们可以假定解决此问题的最快方法是使用max_char took: 11.161055726999999
max_char1 took: 13.953004615000001
max_char2 took: 14.024967180999997
max_char3 took: 37.395588314
容器。
答案 0 :(得分:1)
您表示使用了timeit
,但最初并未提供测试数据。测试数据的大小会严重影响您正在测量的时间。如果测试数据太小,则只是在测量相对开销。
此外,尽管您对标准的python例程通常已进行了很多优化是正确的,但不一定可以针对要使用它们的特定任务对其进行优化,尽管您可以编写自己的例程。例如,在return max(str, key=str.count)
的情况下,很有可能一次又一次地对每个字符执行str.count
,并尽可能有效地对它们进行计数。而您的实现只对字符进行一次迭代。从max_char1
的O(n + n)到max
的O(n ^ 2)与str.count
组合。
max_char
速度慢,令人惊讶,因为它几乎可以完全满足您的需要。在较长的字符串上进行测试时,它比代码要快。
其他一些注意事项:
str
作为变量名是一个非常糟糕的主意,因为它掩盖了基本的Python str
类型。[a-z]
或类似的某种字符,那么最好是初始化一个数据结构,该数据结构允许您更快速地具体计数那些字符,而不是依赖于Counter
或dict
。仅运行简单的测试似乎表明,比内置Python例程更快的任何事情可能都必须是C。例如:
def my_simple(s):
result = [0] * 256
for c in s:
result[ord(c)] += 1
return chr(result.index(max(result)))
速度仍然是Counter(s).most_common(1)[0]
的两倍。