4

IANAサブタグを解析し(カスケード文字列分割、pythonicの方法を参照)、8600タグのリストを作成しました。

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

たとえば、リストにあるかどうかを確認したいと思いmytag="ro"ます。これを行うための最速の方法は何ですか。

最初の解決策:

if mytag in tags:
    print "found"

2番目の解決策:

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

3番目の解決策:リストを次のような大きな文字列に変換してから、'|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

いくつかのコメント

  • に置き換える必要がありSetますset...
  • setテストを実行する前に、長い文字列を作成します
  • あなたのリストからランダムな要素をとるtagsことは確かに行く方法です。

%timeitIPythonでの使用例として:

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

自分で確認できます。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が好きです。比較の前にリストに追加の処理を行わないため、提示した選択肢からも最高のパフォーマンスが得られるはずです。

パフォーマンスをテストする方法については...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

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. ストリングソリューションは、時間測定に結合を含めずに、2番目を速度として測定します。
  3. 驚いたことに、リストは最後です。
于 2012-09-28T12:29:19.873 に答える
1

オプション#1は、リスト全体を調べる必要がないため(セットを作成するには、リスト全体を調べる必要があります)、1回限りの使用で最速である必要がありますが、#2は、次のすべての実行で最速になります。 (set()を1回だけビルドする場合)、それは小さな一定時間で動作するためです。

于 2012-09-28T13:59:59.117 に答える