21

間隔を暗黙的に定義する一連のエンドポイントを指定して、間隔に数値が含まれているかどうかを確認し、対応する (計算可能な方法で関連付けられていない) を返す関数をリファクタリングしています。現在作業を処理しているコードは次のとおりです。

if p <= 100:
    return 0
elif p > 100 and p <= 300:
    return 1
elif p > 300 and p <= 500:
    return 2
elif p > 500 and p <= 800:
    return 3
elif p > 800 and p <= 1000:
    return 4
elif p > 1000:
    return 5

これは IMO にとって非常に恐ろしいことであり、間隔と戻り値の両方がハードコードされているという点で欠けています。もちろん、任意のデータ構造の任意の使用が可能です。

4

6 に答える 6

50
import bisect
bisect.bisect_left([100,300,500,800,1000], p)

ここにドキュメント: bisect

于 2009-07-29T09:47:54.830 に答える
3

これを試すことができます:

def check_mapping(p):
    mapping = [(100, 0), (300, 1), (500, 2)] # Add all your values and returns here

    for check, value in mapping:
        if p <= check:
            return value

print check_mapping(12)
print check_mapping(101)
print check_mapping(303)

生成:

0
1
2

Python ではいつものように、それを行うためのより良い方法があります。

于 2009-07-29T09:43:35.353 に答える
3

それは確かに非常に恐ろしいです。ハードコーディングを行わないという要件がなければ、次のように記述する必要があります。

if p <= 100:
    return 0
elif p <= 300:
    return 1
elif p <= 500:
    return 2
elif p <= 800:
    return 3
elif p <= 1000:
    return 4
else:
    return 5

ハードコーディングなしの要件が満たされ、2 つのテーブルでいくつかのサニティ チェックが行われる、線形および二分探索を使用したルックアップ関数の作成例を次に示します。

def make_linear_lookup(keys, values):
    assert sorted(keys) == keys
    assert len(values) == len(keys) + 1
    def f(query):
        return values[sum(1 for key in keys if query > key)]
    return f

import bisect
def make_bisect_lookup(keys, values):
    assert sorted(keys) == keys
    assert len(values) == len(keys) + 1
    def f(query):
        return values[bisect.bisect_left(keys, query)]
    return f
于 2009-07-29T12:48:31.177 に答える
0
def which_interval(endpoints, number):
    for n, endpoint in enumerate(endpoints):
        if number <= endpoint:
            return n
        previous = endpoint
    return n + 1

endpoints次のように、エンドポイントを のリストとして渡します。

which_interval([100, 300, 500, 800, 1000], 5)

編集:

上記は線形検索です。Glenn Maynard の回答は、二分アルゴリズムを使用しているため、パフォーマンスが向上します。

于 2009-07-29T09:47:46.577 に答える
0

別の方法 ...

def which(lst, p): 
    return len([1 for el in lst if p > el])

lst = [100, 300, 500, 800, 1000]
which(lst, 2)
which(lst, 101)
which(lst, 1001)
于 2009-07-29T10:34:49.960 に答える
0

次の行に沿って何かを試してください。

d = {(None,100): 0, 
    (100,200): 1,
    ...
    (1000, None): 5}
value = 300 # example value
for k,v in d.items():
    if (k[0] is None or value > k[0]) and (k[1] is None or value <= k[1]):
        return v
于 2009-07-29T09:42:34.513 に答える