はい、些細な変更ではるかに高速になります。
value_holder = set()
(まあ、あなたもに変更する必要がありますappend
。add
しかし、それでもかなり簡単です。)
リストの代わりにセットを使用すると、各ルックアップはO(N)ではなくO(1)になるため、操作全体はO(N ^ 2)ではなくO(N)になります。つまり、10,000行ある場合、50,000,000回の比較ではなく、10,000回のハッシュルックアップを実行します。
このソリューション(および投稿された他のすべて)に関する1つの注意点は、値がハッシュ可能である必要があることです。blist
それらがハッシュ可能ではないが、比較可能である場合でも、(たとえば、ライブラリから)ソートされたセットを使用することにより、O(N ^ 2)の代わりにO(NlogN)を取得できます。ハッシュ可能でもソート可能でもない場合…まあ、「最初のチェック」として使用するハッシュ可能(またはソート可能)なものを生成し、実際の一致については「最初のチェック」の一致のみをウォークする方法を見つけたいと思うでしょう。 、O(NM)に移動します。ここで、Mはハッシュ衝突の平均数です。
標準ライブラリのドキュメントのレシピにどのようunique_everseen
に実装されているかを確認することをお勧めします。itertools
辞書には実際には順序がないため、「最初の」複製を選択する方法がないことに注意してください。任意に1つ取得します。その場合、これを行う別の方法があります。
inverted = {v:k for k, v in d.iteritems()}
reverted = {v:k for k, v in inverted.iteritems()}
(これは事実上、処理なしの装飾-プロセス-非装飾イディオムの形式です。)
しかし、を構築してdict
フィルタリングする代わりに、読みながらフィルタリングすることで、物事をより良くすることができます(よりシンプルで、より速く、よりメモリ効率が高く、順序を維持できます)。基本的に、あなたが進むにつれて、set
一緒に保ちます。dict
たとえば、これの代わりに:
mydict = {}
for line in f:
k, v = line.split(None, 1)
mydict[k] = v
mapp = {}
value_holder = set()
for i in mydict:
if mydict[i] not in value_holder:
mapp[i] = mydict[i]
value_holder.add(mydict[i])
これを行うだけです:
mapp = {}
value_holder = set()
for line in f:
k, v = line.split(None, 1)
if v not in value_holder:
mapp[k] = v
value_holder.add(v)
実際、これをまとめたものを書くことを検討することをお勧めしますone_to_one_dict
(または、PyPIモジュールとActiveStateレシピを検索して、誰かがすでにそれを書いているかどうかを確認します)。
mapp = one_to_one_dict()
for line in f:
k, v = line.split(None, 1)
mapp[k] = v