Pythonのバイセクトモジュールについて話す

bisectモジュールには、2つの主要な関数(bisectとinsort)が含まれています。これらの関数は、内部でバイナリ検索アルゴリズムを使用して要素を検索し、順序付けられた順序で要素を挿入します。

sth
を2つの等しい部分に分割するためのbisect / baɪˈsekt /

1バイセクト機能

Luciano Ramalhoは、干し草の山から針を見つけて、bisect.bisectとbisect.bisect_leftの使用方法を説明する例を示しました。

HAYSTACK = [1, 4, 5, 6, 8, 12, 15, 20, 21, 23, 23, 26, 29, 30]
NEEDLES = [0, 1, 2, 5, 8, 10, 22, 23, 29, 30, 31]

ROW_FMT = '{0:2d} @ {1:2d}    {2}{0:<2d}'


def demo(bisect_fn):
    for needle in reversed(NEEDLES):
        position = bisect_fn(HAYSTACK, needle)
        offset = position * '  |'
        print(ROW_FMT.format(needle, position, offset))


if __name__ == '__main__':

    if sys.argv[-1] == 'left':
        bisect_fn = bisect.bisect_left
    else:
        bisect_fn = bisect.bisect

    print('DEMO:', bisect_fn.__name__)
    print('haystack ->', ' '.join('%2d' % n for n in HAYSTACK))
    demo(bisect_fn)

動作結果:

DEMO: bisect_right
haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |29
23 @ 11      |  |  |  |  |  |  |  |  |  |  |23
22 @  9      |  |  |  |  |  |  |  |  |22
10 @  5      |  |  |  |  |10
 8 @  5      |  |  |  |  |8 
 5 @  3      |  |  |5 
 2 @  1      |2 
 1 @  1      |1 
 0 @  0    0 

Python関数の機能の1つは、例のbisect_fnのように、関数名を引数として使用できることです。そうすることで、関数がより柔軟になります。関数名をプログラム実行パラメーターとして使用し、動的にロードできます。

HAYSTACKは干し草の山の山であり、NEEDLESは針の山です。干し草の山で針を見つけることは、本質的に一連の数字の中から特定の数字を探すことです。

カスタムdemo(bisect_fn)関数は、最初に位置を計算し、次にその位置を使用して必要なセパレーターの数を印刷オフセットとして計算し、最後に定義された形式で印刷します。

str.format()は文字列をフォーマットするために使用され、実際のパラメーターの位置を指定できます。{0:2d}と同様の構文では、0は最初の入力パラメーターを意味し、:2dは全長を意味し、十分でない場合はスペースがプレースホルダーとして使用されます。dは10進符号付き整数を意味します。

配置はstr.format()形式で設定することもできます。^、<、>は、それぞれ中央、左、右を意味します。したがって、{0:<2d}は、最初の入力パラメータが左寄せされ、2桁の10進符号付き整数を占めることを意味します。

__name__これはpythonの組み込みクラス属性であり、pythonプログラムに存在し、対応するプログラムの名前を表します。メインスレッドの場合、その組み込み名は__main__です。

プログラムの実行時にleftパラメーターが追加されると、bisect_left関数がプログラムのカスタム関数内で呼び出されます。bisect関数は、実際にはbisect_right関数のエイリアスです。

bisect_left関数とbisect関数の違いは次のとおりです。

  1. bisect_left関数は、元のシーケンスで挿入された要素と等しい要素の位置を返します。新しい要素が挿入されると、新しい要素はそれに等しい要素のに配置されます。
    2.bisect関数は、要素のequalに挿入された後、元のシーケンスの位置を返します。新しい要素を挿入すると、新しい要素は、その要素がbackに等しい状態で配置されます

bisect_left関数操作の結果:

DEMO: bisect_left
haystack ->  1  4  5  6  8 12 15 20 21 23 23 26 29 30
31 @ 14      |  |  |  |  |  |  |  |  |  |  |  |  |  |31
30 @ 13      |  |  |  |  |  |  |  |  |  |  |  |  |30
29 @ 12      |  |  |  |  |  |  |  |  |  |  |  |29
23 @  9      |  |  |  |  |  |  |  |  |23
22 @  9      |  |  |  |  |  |  |  |  |22
10 @  5      |  |  |  |  |10
 8 @  4      |  |  |  |8 
 5 @  2      |  |5 
 2 @  1      |2 
 1 @  0    1 
 0 @  0    0 

公式のpythonドキュメントには、bisect関数を使用してテストスコアを出力するサンプルプログラムも記載されています。

def grade(score, breakpoints=[60, 70, 80, 90], grades='FDCBA'):
    i = bisect.bisect(breakpoints, score)
    return grades[i]

if __name__ == '__main__':
  results = [grade(score) for score in [33, 99, 77, 70, 89, 90, 100]]
    logging.info('results -> %s', results)

動作結果:

INFO - results -> ['F', 'A', 'C', 'C', 'B', 'A', 'A']

カスタムgrade()は、次の3つのパラメーターを定義します。

パラメータ名 説明
スコア テストの点数
ブレークポイント スコアレベルの境界値。ここでは、90以上、80〜89、70〜79、60〜69、および60未満の5つのレベルに分けられます。
グレード 評価ポイントの範囲。

grade()関数は、最初に入力スコアに従ってbisect()関数を介してその位置を見つけ、次にこの位置をgradesシーケンスに渡して、評価スコアを取得します。

メインスレッドでは、文法のforを介して学生の成績を表すシーケンスを繰り返し、その成績をgrade()関数に渡して評価スコアを計算し、最後にシーケンスを介して一度に出力します。

2ソート機能

並べ替えは時間のかかる作業であるため、順序付けられたシーケンスの場合、要素を追加するときに順序を維持するのが最善です。insort関数は、挿入時にシーケンスが常に順序付けられるようにします。

    SIZE=10
    my_list=[]
    for i in range(SIZE):
        new_item=random.randrange(SIZE*3)
        bisect.insort(my_list,new_item)
        print('%2d -> '% new_item,my_list)

動作結果:

18 ->  [18]
 8 ->  [8, 18]
21 ->  [8, 18, 21]
 5 ->  [5, 8, 18, 21]
19 ->  [5, 8, 18, 19, 21]
13 ->  [5, 8, 13, 18, 19, 21]
20 ->  [5, 8, 13, 18, 19, 20, 21]
 4 ->  [4, 5, 8, 13, 18, 19, 20, 21]
15 ->  [4, 5, 8, 13, 15, 18, 19, 20, 21]
 2 ->  [2, 4, 5, 8, 13, 15, 18, 19, 20, 21]

randrange()は、指定されたパラメーター範囲内のランダムな数値を返しますが、境界値は含まれません。

ご覧のとおり、挿入するたびに、シーケンスは常に順番になります。

print('%2d -> '% new_item,my_list)%sフォーマット構文が採用され、%2dはnew_item値のフォーマットを定義し、my_listはフォーマットの後に自動的にハングします。したがって、2番目のパーセント記号の後に括弧はなく、フォーマットする必要のあるパラメーターは丸で囲まれています。

Insortにはinsort_leftという兄弟もあり、最下層はbisect_leftを使用しています。insort_left関数は、新しい要素を同じ要素の前に配置します。


さらに、bisect関数とinsort関数には、検索するシーケンスの範囲を狭めるために使用できる2つのオプションパラメーター(loとhi)があります。loのデフォルト値は0で、hiのデフォルト値はシーケンスの長さです。

おすすめ

転載: blog.csdn.net/deniro_li/article/details/108894298