2016-07-10 10 views
1

にカンマ区切りの文字列を分割し、私のようなものありませんいくつかのコードがあります。パイソン:直接セット

if string in comma_delimited_string.split(','): 
    return True 

This websiteはセットとdictsとメンバーシップのテストは非常に速く、そのリストやタプルであると述べています。 set(comma_delimited_string.split(','))を実行すると、リストがセットに変換される前にリストが作成されているため、スピードが向上しないことがわかります(少なくとも、タイムアウトすると遅くなるようです)。

私は(私のコードへの真のメリットよりも、主に好奇心から)、その後、思っていた、comma_delimited_string.split(',')のと同じ効果を達成するための方法があるが、直接セットを作成し、リストの代わりに、スピードアップのつもりで上記の操作は?

答えて

2

いいえ、str.split操作は常にリストを返し、それをsetに変換しようとすると時間がかかります。 str.splitはCでimplementeがあるため、また、直接生成し、独自の手作りsplitを書くことセットは、遅くなりますが

ノート(ソースコードはObjects/stringlib/split.h下でなければなりません)があなたのstringは、カンマが含まれているしない場合

if string in comma_delimited_string: 

stringにカンマが含まれている場合は、あなたのテストは常にのでデフで(失敗します:あなたはstringその後、あなただけ行うことができ、splitによって返される要素の部分文字列ではないことを期待します要素text.split(',')は決して1つを含んでいません。

あなたが何か持っている時には、上記の条件が失敗する場合がある。この場合には"a" in ["aaa", "bb", "c"]が失敗したので

if "a" in "aaa,bb,c".split(',') 

を。

別の方法としては、正規表現を使用することができます。

import re 
if re.search(r'(^{0},)|(,{0},)|(,{0}$)|(^{0}$)'.format(re.escape(string)), comma_delimited_string): 

私はこれがより速くなるかどうかわかりませんが、それはおそらくあなたの入力に依存します。

+0

@Bakuriu返事ありがとうございます - 私の場合は、曖昧な文書番号(例えば、文書が「10」と「103」の場合があります)を見ているので、純粋な 'string in comma_delimited_string'全く適用できません。ですから、カンマで区切られた文字列を '.split'のようにCに直接書くことができるでしょうか? ....いつでもすぐにやっていない。 – dieggsy

+0

@therockmandolinistはい、それは私が言っていることです。 'split'のコードをコピーして貼り付け、リストの代わりにセットを使う必要があります。そのチェックができるだけ速くなければならない場合にのみ、私はそれを行うことが大変面倒です。 – Bakuriu

3

何かをセットに変換するには、それを反復する必要があるという事実を無視しています。その繰り返しは元のリストを検索するために既に行っているのとまったく同じです。だから、オーバーヘッドだけでこれを行うことに利点はありません。

あなたが変換のコストを償却することができるので、あなたがそれを何度もやっているならば、セットに対する検索はより効率的です。しかし、変換自体は常にリニアスキャンになります。それを避ける方法はありません。

+0

私の推論の行は、例えば、すでに作成されたリストのためのものであり、 1、2、3、... '1000000'、 '' 1000000 'in my_set'は、少なくとも私がタイムアウトしたとき、 '' 1000000'よりも速いです。そのため、コンマ区切り文字列を '.split'メソッドと同じ時間がかかるセットに直接変換するメソッドがあれば、実際のメンバシップテストは高速化されるかもしれません。 – dieggsy

+0

思考:コンマで区切られた文字列を '.split'のように高速に変換する唯一の方法は、何らかの形で、Cでカスタム実装を書くことかもしれないと思います。 – dieggsy

1

既存のセットのメンバシップテストはリスト(O(n))より速く(O(1))、文字列からセットを作成する必要があります。 n)。時間の複雑さについては何もできません。

あなただけの代わりに、中間データ構造を構築する文字列をスキャンすることによって、しかし一定の係数でテストをスピードアップすることができます:あなたは本当に良い理由がない限り

(',%s,' % string) in (',%s,' % comma_delimited_string) 

はこれを使用しないでください。

+0

ええ、 '.split'メソッドがそれをリストに変えてメンバシップテストをスピードアップするのと同じくらい時間をかけて、文字列をセットに変換することを意味しました。興味深い返答ですが、これは任意の文字列のリストのメンバシップをチェックするのと同じ方法で動作します。なぜあなたはそれを使用すべきではないと言いますか? – dieggsy

+0

私のテストデータでは、これは 'split'では2.5μsの代わりに500nsしかかかりませんでした。しかし、読みやすさの観点からは、スピードが最重要ではない場合、私はスプリットを行うべきだと考えています。 –

+0

@tobias_k私はあなたのことをよく理解しています。それは、非常に複雑な最適化には非常に意味があります。私はそれが好みの問題かもしれないと思うが、私は一般的に、(この場合のように)犠牲がそれほど大きくない場合には、読みやすさよりもパフォーマンスを最適化する方が望ましいと思う。私はちょうど最近_really_コーディングになっているので、おそらくあなたは私に別のものを説得することができます。 – dieggsy