Python 为什么字符串搜索比列表搜索和集合搜索最快?
我正在解决一些有竞争力的编码挑战。当我在列表中搜索时,我的解决方案超出了时间限制,但当我在字符串中搜索时被接受 下面是一个示例代码: 代码Python 为什么字符串搜索比列表搜索和集合搜索最快?,python,string,python-2.7,Python,String,Python 2.7,我正在解决一些有竞争力的编码挑战。当我在列表中搜索时,我的解决方案超出了时间限制,但当我在字符串中搜索时被接受 下面是一个示例代码: 代码 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(9999
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上获得的**输出可能因系统而异,但趋势相同
我发现字符串搜索速度快得难以置信。我在谷歌上搜索了一下,但没有找到令人满意的理由。请帮助我理解为什么字符串搜索最快 您的测试是有偏差的,您需要使用
设置
参数来忽略创建列表
或设置
>>> 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
也就是说,对于
str
和list
的操作中的是线性的O(N)
,set
是常量O(1)
(忽略大量哈希冲突)。因此,对于一个更大的例子来说,set
将是最快的,而str
和list
将非常相似。这与实际搜索速度几乎没有关系,与必须查找全局名称(set
或list
)并调用该全局名称有关(包括帧保存和恢复)
仅在
操作员中测试实际的,而不是在呼叫时:
>>> 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数组上迭代并比较字节比在动态数组中比较对象要快,在动态数组中,您无法预先知道所有对象都是同一类型。实际上,检查set
的成员关系比list和string becau更快使用哈希表和它O(1),但这里看到的不同是因为将字符串转换为set和list。因此,尝试使用{'A','I','E','U','O'}
和['A','I','E','U','O']
,因为您的示例集非常小,O(1)
forset
比O(N)有优势
对于其他人来说并不重要。而且设置(创建集合
和列表
)无论如何都是O(N)
。搜索字符串比列表
更快,因为它的结构更简单(它包含字符数组,而不是对字符串对象的引用)。