Python:在枚举中查找字符串的最快方法

时间:2012-09-28 09:51:06

标签: python string search python-2.7 enumeration

解析了IANA子标签(请参阅Cascaded string split, pythonic way)并列出了8600个标签:

tags= ['aa',
       'ab',
       'ae',
       'af',
       'ak',
       'am',
       'an',
       'ar',
       # ...

我想查看示例mytag="ro"是否在列表中: 最快的方法是什么:

第一个解决方案:

if mytag in tags:
    print "found"

第二个解决方案:

if mytag in Set(tags):
    print "found"

第三个解决方案:在一个大字符串中转换列表,如:'|aa|ab|ae|af|ak|am|an|ar|...',然后查看字符串是否在另一个字符串中:

tags = '|aa|ab|ae|af|ak|am|an|ar|...'
if mytag in tags:
    print "found"

还有其他方法吗?哪个是最快的,这是否已经测量过,如果不是我怎么能自我测量(我从列表中取一个随机元素或者我应该拿最后一个然后测试它,有人可以为'天文台'提供python代码)吗?

6 个答案:

答案 0 :(得分:6)

由于我无法访问原始字符串,因此任何测试都会有偏差。但是,你问了一个天文台?检查timeit模块,该模块旨在为一些代码段提供时间。

请注意,如果您使用IPython%timeit是一个神奇的函数,可以轻松地执行函数,如下所示。

一些评论

  • 您应该将Set替换为set ...
  • 在运行任何测试之前构建您的set和长字符串
  • tags列表中取一个随机元素是真正的方法。

作为在IPython中使用%timeit的一个例子:

tags = ['aa','ab','ae','af','ak','an','ar']
tags_set = set(tags)
tags_str = "|".join(tags)

%timeit 'ro' in tags
1000000 loops, best of 3: 223 ns per loop
%timeit 'ro' in tags_set
1000000 loops, best of 3: 73.5 ns per loop
%timeit 'ro' in tags_str
1000000 loops, best of 3: 98.1 ns per loop

答案 1 :(得分:2)

与时间或性能无关,但您可能不会因为以不同方式构建数据而更加担心此类事情。

查看您之前的帖子,您接受的答案包含一个函数iana_parse,它产生了一个词典。所以,如果你知道你在寻找解析前的时间,那么你可以这样做:

looking_for = {'ro', 'xx', 'yy', 'zz'}
for res in iana_parse(data): # from previous post
    if res['Subtag'] in looking_for:
        print res['Subtag'], 'was found'

否则(或与之结合使用),您可以从该函数构建一个dict并使用:

subtag_lookup = {rec['Subtag']:rec for rec in iana_parse(data)}

ro = subtag_lookup['ro']
print ro['Description']

在某些时候,如果您只想要一个子标签列表,请使用:

subtags = list(subtag_lookup)

答案 2 :(得分:1)

你可以自己检查一下。只需使用timeit模块..

timeit.Timer()可能对您有用..

或者,您也可以使用time模块: -

import time
ct = time.clock()
if mytag in tags:
    print "found"
print "diff: ", time.clock() - ct

答案 3 :(得分:1)

我更喜欢#1。它应该从您提供的选项中为您提供最佳性能,因为您在比较之前没有对列表进行额外处理。

至于如何测试表现...... timeit就是你想要的。

import timeit
s1 = """
tags= ['aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar']
mytag = 'ro'
if mytag in tags:
    print 'found'
"""
s2 = """
tags= ['aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar']
mytag = 'ro'
if mytag in set(tags):
    print 'found'
"""
s3 = """
tags= ['aa', 'ab', 'ae', 'af', 'ak', 'am', 'an', 'ar']
mytag = 'ro'
if mytag in '|'.join(tags):
    print 'found'
"""

print(timeit.Timer(s1, 'gc.enable()').timeit())
print(timeit.Timer(s2, 'gc.enable()').timeit())
print(timeit.Timer(s3, 'gc.enable()').timeit())

>>> 
0.261634511713
0.476344575019
0.282574283666

答案 4 :(得分:1)

我自己使用此代码完成了测试,您可以在IPython控制台中使用%cpaste并粘贴下面的代码。

#Get IANA language defs
import urllib
import pprint
import timeit
import IPython
import random
f = urllib.urlopen("http://www.iana.org/assignments/language-subtag-registry")
#lan.split("%%") .split("\n").split(":")
lan=f.read()
def iana_parse(data):
    for record in data.split("%%\n"):
        # skip empty records at file endings:
        if not record.strip():
            continue
        rec_data = {}
        for line in record.split("\n"):
#            key, value = line.split(":") doesn't work
            key, value = line.partition(':')[::2]
#            key, _, value = line.partition(':')
            rec_data[key.strip()] = value.strip() 
        yield rec_data

tags =[]

for k in iana_parse(lan):
#    print k
    if "Subtag" in k: tags.append(k["Subtag"])
#maybe store it in a shelve http://docs.python.org/library/shelve.html

tags_set = set(tags)
tags_str = "|".join(tags)
print "Search 'ro'" 
print "List:"
%timeit 'ro' in tags
print "Set:"
%timeit 'ro' in tags_set
print "String:"
%timeit 'ro' in tags_str

random_tag = tags[random.randint(0,len(tags)-1)]
print "Search random" 
print "List:"
%timeit random_tag in tags 
print "Set:"
%timeit random_tag in tags_set 
print "String:"
%timeit random_tag in tags_str

结果是:

Search 'ro'
List: 1000000 loops, best of 3: 1.61 us per loop
Set: 10000000 loops, best of 3: 45.2 ns per loop
String: 1000000 loops, best of 3: 239 ns per loop

Search random
List:10000 loops, best of 3: 36.2 us per loop
Set:10000000 loops, best of 3: 50.9 ns per loop
String:100000 loops, best of 3: 4.88 us per loop

所以顺序是:

  1. 如果从列表中初始化集合并且未包含在测量中,则设置是最快的。
  2. String solution测量第二个速度,也不包括时间测量中的连接。
  3. 令人惊讶的是,这个名单是最后一个。

答案 5 :(得分:1)

选项#1应该是一次性使用最快的,因为它甚至不需要遍历整个列表(构建一个需要通过整个列表的集合),而#2将是最快的所有下一次运行(如果你只构建一次set()),因为它将在很小的恒定时间内工作。