【问题标题】:Why is string search fastest as compared to list search and set search?为什么字符串搜索比列表搜索和集合搜索快?
【发布时间】:2015-08-17 11:34:25
【问题描述】:

我正在解决一些竞争性的编码挑战。我的解决方案是在列表中搜索时超出时间限制,但在我搜索字符串时被接受。

下面是示例代码:

代码

import timeit

list = timeit.Timer("'A' in list('AEIOU')")
set = timeit.Timer("'A' in set('AEIOU')")
string = timeit.Timer("'A' in 'AEIOU'")

print 'List search :',list.timeit(999999)
print 'Set search',set.timeit(999999)
print 'String search',string.timeit(999999)

输出

List search : 1.0873670578
Set search 1.0083398819
String search 0.0997061729431

*此输出是在 ideone.com 中获得的...http://ideone.com/5FxkX2
**输出可能因系统而异,但趋势相同。

我发现字符串搜索速度非常快。我用谷歌搜索,但没有找到令人满意的理由。请帮助我理解为什么字符串搜索最快?

【问题讨论】:

  • 实际上,检查set 的成员身份比列表和字符串要快,因为使用哈希表并且它 O(1),但您在这里看到的不同之处在于将字符串转换为设置并列出。所以试试{'A', 'I', 'E', 'U', 'O'}['A', 'I', 'E', 'U', 'O']
  • 因为您的示例集非常小,所以 O(1)set 相对于 O(N) 的其他优势并不重要。无论如何,设置(setlist 的创建)是O(N)。搜索字符串比list 更快,因为它是一个更简单的结构(它包含一个字符数组而不是对字符串对象的引用)。

标签: python string python-2.7


【解决方案1】:

您的测试有偏差,您需要使用setup 参数来忽略创建listset 的时间

>>> timeit.timeit("'A' in l", "l = list('AEIOU')")
0.06389708405846951
>>> timeit.timeit("'A' in s", "s = set('AEIOU')")
0.05960524183085081
>>> timeit.timeit("'A' in s", "s = 'AEIOU'")
0.05756433387793081

话虽如此,strlistin 操作是线性的 O(N)set 是恒定的 O(1)(忽略大量哈希冲突)。因此,对于更大的示例,set 将是最快的,strlist 将非常相似。

【讨论】:

    【解决方案2】:

    这与实际的搜索速度几乎没有关系,而一切都与必须查找全局名称(setlist)并调用该全局名称(包括帧保存和恢复)有关。

    测试实际的in操作符单独,而不是用调用:

    >>> import timeit
    >>> timeit.Timer("'A' in l", "l = list('AEIOU')").timeit(999999)
    0.0490870475769043
    >>> timeit.Timer("'A' in s", "s = set('AEIOU')").timeit(999999)
    0.0507349967956543
    >>> timeit.Timer("'A' in s", "s = 'AEIOU'").timeit(999999)
    0.04982495307922363
    

    现在时间太近了,因为您的对象太小了。使用更大的输入来实际看到差异。

    只是使用更多的字符已经在一定程度上增加了对比度:

    >>> timeit.Timer("'A' in l", "from string import ascii_letters, digits, whitespace; l = list(ascii_letters + digits + whitespace)").timeit(999999)
    0.38520193099975586
    >>> timeit.Timer("'A' in s", "from string import ascii_letters, digits, whitespace; s = set(ascii_letters + digits + whitespace)").timeit(999999)
    0.046868085861206055
    >>> timeit.Timer("'A' in s", "from string import ascii_letters, digits, whitespace; s = ascii_letters + digits + whitespace").timeit(999999)
    0.06492304801940918
    

    现在set() 对象开始获胜,列表对象显示其速度较慢。

    您还应该测试 否定 情况,其中字符 出现在对象中:

    >>> timeit.Timer("'\xff' in l", "from string import ascii_letters, digits, whitespace; l = list(ascii_letters + digits + whitespace)").timeit(999999)
    0.909243106842041
    >>> timeit.Timer("'\xff' in s", "from string import ascii_letters, digits, whitespace; s = set(ascii_letters + digits + whitespace)").timeit(999999)
    0.05034899711608887
    >>> timeit.Timer("'\xff' in s", "from string import ascii_letters, digits, whitespace; s = ascii_letters + digits + whitespace").timeit(999999)
    0.09932804107666016
    

    set() 对象在这里真的很出色。

    请注意,在这两种情况下,字符串搜索仍然优于列表搜索;这是因为遍历 C 数组并比较字节比比较动态数组中的对象要快,在动态数组中,您无法预先知道所有对象都是同一类型。

    【讨论】:

      猜你喜欢
      • 2021-10-24
      • 2015-10-24
      • 2013-01-20
      • 1970-01-01
      • 2018-09-19
      • 2012-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多