2011-09-02 6 views
24

Pythonでは、ソートされたリストの最初の値のインデックスがスレッショルドよりも大きいことをどのようにして知ることができますか?Pythonでは、ソートされたリストの最初の値のインデックスがしきい値よりも大きいことをどのようにして知ることができますか?

私はこれを行ういくつかの方法(線形検索、手書き二分法など)を考えることができますが、それを行うのに合理的に効率的な方法を探しています。それはおそらくかなり一般的な問題だから、私は経験豊かなSOersが助けることができると確信しています!

ありがとうございます!

答えて

45

bisectをご覧ください。

import bisect 

l = [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] 

bisect.bisect(l, 55) # returns 7 

は線形検索と比較:

timeit bisect.bisect(l, 55) 
# 375ns 


timeit next((i for i,n in enumerate(l) if n > 55), len(l)) 
# 2.24us 


timeit next((l.index(n) for n in l if n > 55), len(l)) 
# 1.93us 
+0

2つ目の方法は、列挙がなくても単純なループを使用してlist.index()を戻す方が高速です。しかし、バイセクト・ソリューションにはどこもありません。 – rplnt

+0

@rplnt - ありがとう、私はそれを比較に追加しました。あなたが正しいです、それは列挙より速いです。 – eumiro

1

あなたはitertoolsを使用して列挙/ジェネレータのアプローチよりも良い時間を頂く場合がございます。私はitertoolsが私たち全員のパフォーマンスの邪魔者のために基礎となるアルゴリズムのより速い実装を提供すると思います。しかし、bisectはまだより速いかもしれません。

from itertools import islice, dropwhile 

threshold = 5 
seq = [1,4,6,9,11] 
first_val = islice(dropwhile(lambda x: x<=threshold, seq),0,1) 
result = seq.index(first_val) 

私はここに示す二分アプローチと限りイディオム/速度など、ドキュメントの例では、あなたの質問のためにリストされているものの違いについて疑問に思います。彼らは値を見つける方法を示していますが、最初の行に切り捨ててインデックスを返します。私はそれが "bisect_right"の代わりに "bisect_right"と呼ばれているので、おそらく一方向からしか見えないと思います。あなたのリストがソートされ、あなたがより大きい値を求めていることを考えると、これは最大の検索経済かもしれません。

from bisect import bisect_right 

def find_gt(a, x): 
    'Find leftmost value(switching this to index) greater than x' 
    return bisect_right(a, x) 

興味深い質問。

関連する問題