在字符串中查找最常用的字符的最快方法是什么

时间:2019-08-12 02:17:35

标签: python

我编写了几个函数,它们接受一个字符串并返回其中最常用的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


我已经使用timeit1000000迭代对它们进行了测试,其中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 容器。

1 个答案:

答案 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类型。
  • 根据字符串中期望的字符,您可能有更快的选择。例如,如果您的字符串是UTF并且可以包含任何有效的UTF字符,则给定的解决方案可能接近最佳值。但是,如果您的字符串只能包含非常有限范围内的字符,例如[a-z]或类似的某种字符,那么最好是初始化一个数据结构,该数据结构允许您更快速地具体计数那些字符,而不是依赖于Counterdict

仅运行简单的测试似乎表明,比内置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]的两倍。