2009-07-29 8 views
11

間隔を暗黙的に定義する一連のエンドポイントを指定して、間隔に数値が含まれているかどうかを確認し、対応する(計算可能な方法では関係しない)関数をリファクタリングしています)。 今の仕事を処理しているコードがある:IMOかなり恐ろしいであり、その間隔の両方に欠け、戻り値がハードコードされてPython:間隔から値へのマッピング

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 

。 任意のデータ構造を使用することはもちろん可能です。

答えて

35
import bisect 
bisect.bisect_left([100,300,500,800,1000], p) 
+0

+1私はこれが好きです。あなたは毎日何か新しいことを学びます。 – kjfletch

+0

+1:信じられないほど! –

+1

本当に印象的です。スーパークリーン、私は非常に速くも信じています。 文字列のように非自然順序付けや何か他のものが必要な場合は、簡単に拡張することもできます。 import bisect n = bisect。bisect_left([100,300,500,800,1000]、p) a = [「不在」、「低い」、「平均」、「高い」、「非常に高い」、「極端な」 [n] – Agos

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 
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) 

が生成する:常にPythonで同様

0 
1 
2 

を、あるでしょうそれを行うためのよりよい方法。

+0

p> 1000の場合は考慮しません! – stefanw

+0

これが私が指定した理由です:「あなたはこのことをやってみることができます」 – kjfletch

+0

最後の文は、何かを行うための1つの明らかな方法しか持たないというpythonの哲学を考えれば皮肉です。 – sykora

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の答えは、二分アルゴリズムを使用しているため、より良い性能を発揮します。

+0

「前の」ケーパを失う。それはかなり冗長です。 –

+0

ええ、そうです、私は元のコードが私にそれを "インスピレーション"したと思います。ところで、あなたの命令の使用は、ある人に少し痛いかもしれません。 – Steef

+0

@Steef:あなたのお暇の時にあなたの答えを書き直すかもしれないという謙虚な考えを考えてみてください。**あなたの答えにはまだ冗長なコード**が含まれています。 –

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) 
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 

は、線形およびバイナリ検索を使用して、両方の検索機能の作成例、満たさ無hardcodingsの要件に、そしてカップル

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 
+0

より一般化された/ハードコーディングされていない形式のため投票が最も多く、より深いものであるため、 – JAB

関連する問題