web-dev-qa-db-ja.com

新しいアイテムをソート済みリストに挿入してソートを維持できるインデックスを見つけるにはどうすればよいですか?

a = 132

b = [0, 10, 30, 60, 100, 150, 210, 280, 340, 480, 530]

aは順序付きリストbの6番目の位置にある必要があることを知りたいです。

そうするための最もPythonicな方法は何ですか?

28
est

bisect を使用します。これは最も美しいAPIではありませんが、まさに必要なものです。

bisect.bisectを使用すると、必要なものが正確に返されます。

23
madjar

bisect は、このタスクに最適なPython標準ライブラリのモジュールです。モジュールbisectの関数bisectは、の挿入ポイントのインデックスを提供します。値。

bisectのコード例を挙げましょう

from bisect import bisect
a = 132
b = [0, 10, 30, 60, 100, 150, 210, 280, 340, 480, 530]
print(bisect(b, a))

リストは0から始まるため、結果は5になります。したがって、実際には6番目の位置になります。

あなたが知ることができることは、結果をinsertに使用することです。

index = bisect(b, a)
b.insert(index, a)

または中間変数なし

b.insert(bisect(b, a), a)

これで、b[0, 10, 30, 60, 100, 132, 150, 210, 280, 340, 480, 530]になります。

33
Matthias

エッジケースにはさらに懸念があります。たとえば、前述のbの要素を_(a, c)_の範囲で選択し、を使用してそれらを選択するとします。

_b[idx_a:idx_c]
_

次に、_a, c_が実際にはbの要素である場合について考える必要があります。ご了承ください

_bisect.bisect(b, 10)
bisect.bisect(b, 11)
_

両方ともインデックス2を与えます。したがって、_a=10_の場合、インデックスを1下げる必要があります。幸い、これを正確に実行する関数_bisect.bisect_left_があります。つまり、この例では

_bisect.bisect_left(b, 10)
_

1を与えます。

全体として、左側のインデックスはbisect.bisect_left()と右側のインデックスbisect.bisect_right()bisect.bisect()と同じ)を使用して計算する必要があります。

2
nos