4

解析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 代码)?

4

6 回答 6

6

由于我无法访问原始字符串,因此任何测试都会有偏见。但是,您要的是天文台表?检查timeit模块,旨在计时一些代码片段。

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

一些评论

  • 你应该替换Setset...
  • 在运行任何测试之前构造你的set长字符串
  • 从您的tags列表中随机抽取一个元素确实是可行的方法。

作为%timeit在 IPython 中使用的示例:

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
于 2012-09-28T09:56:08.157 回答
2

与时间或性能无关,但您可以通过以不同的方式构造数据,而不用担心这种事情。

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

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)
于 2012-09-28T10:06:59.070 回答
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
于 2012-09-28T10:02:10.977 回答
1

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

#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. 字符串解决方案作为速度测量第二个,也不包括时间测量中的连接。
  3. 令人惊讶的是,该列表是最后一个。
于 2012-09-28T12:29:19.873 回答
1

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

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

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

import time
ct = time.clock()
if mytag in tags:
    print "found"
print "diff: ", time.clock() - ct
于 2012-09-28T09:57:19.187 回答
1

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

于 2012-09-28T13:59:59.117 回答