1

質問は複雑に聞こえるかもしれませんが、実際には非常に単純ですが、Python で適切な解決策が見つかりません。

のような範囲があります ("8X5000", "8X5099")。ここには任意の数字を指定できるため、範囲 (またはまたは ... ) のいずれかXに該当する数字と一致させたいと考えています。805000..805099815000..815099895000..895099

これどうやってするの?

4

3 に答える 3

3

@TimPietzckerの答えは正しく、Pythonicですが、パフォーマンスの問題が発生します(おそらく、さらにPythonicになります)。値を検索するイテレータを作成します。Pythonが検索を最適化できるとは思っていません。

これにより、パフォーマンスが向上するはずです。

def IsInRange(n, r=("8X5000", "8X5099")):
    (minr, maxr) = [[int(i) for i in l.split('X')] for l in r]
    p = len(r[0]) - r[0].find('X')

    nl = (n // 10**p, n % 10**(p-1))
    fInRange = all([minr[i] <= nl[i] <= maxr[i] for i in range(2)])
    return fInRange

関数内の2行目はネストされたリスト内包表記であるため、少し読みにくいかもしれませんが、次のように設定されます。

minr = [8, 5000]
maxr = [8, 5099]

n = 595049の場合:

nl = (5, 5049)

コードは、範囲を部分に分割し(intに変換している間)、ターゲット番号を部分に分割してから、範囲が部分をチェックします。範囲指定子の複数のXを処理するために、これを拡張することは難しくありません。

アップデート

timeitを使用して相対的なパフォーマンスをテストしました。

def main():
    t1 = timeit.timeit('MultiRange.in_range(985000)', setup='import MultiRange', number=10000)
    t2 = timeit.timeit('MultiRange.IsInRange(985000)', setup='import MultiRange', number=10000)

    print t1, t2
    print float(t2)/float(t1), 1 - float(t2)/float(t1)        

Python2.7.2を実行している32ビットのWin7マシンでは、私のソリューションは@TimPietzckerのソリューションよりもほぼ10倍高速です(具体的には、12%の時間で実行されます)。範囲のサイズを大きくすると、悪化するだけです。いつ:

ranges=("8X5000", "8X5999")

パフォーマンスの向上は50倍です。最小範囲でも、私のバージョンは4倍速く実行されます。

@PaulMcGuireが提案したパフォーマンスパッチを使用するとin_range、私のバージョンは3倍速く実行されます。

アップデート2

@PaulMcGuireのコメントに動機付けられて、私は先に進み、関数をクラスにリファクタリングしました。これが私のものです:

class IsInRange5(object):
    def __init__(self, r=("8X5000", "8X5099")):
        ((self.minr0, self.minr1), (self.maxr0, self.maxr1)) = [[int(i) for i in l.split('X')] for l in r]
        pos = len(r[0]) - r[0].find('X')
        self.basel = 10**(pos-1)
        self.baseh = self.basel*10
        self.ir = range(2)

    def __contains__(self, n):
        return self.minr0 <= n // self.baseh <= self.maxr0 and \
            self.minr1 <= n % self.basel <= self.maxr1

これによりギャップは埋められましたが、範囲不変条件(両方)を事前に計算した後でも、@ PaulMcGuireの方が50%長くかかりました。

于 2012-11-28T08:51:34.403 に答える
1
range = (80555,80888)

x = 80666

print range[0] < x < range[1]

多分あなたが探しているもの...

于 2012-11-28T06:52:18.293 に答える
1

Python 3 の例 (Python 2 では、xrangeの代わりに使用range):

def in_range(number, ranges=("8X5000", "8X5099")):
    actual_ranges = ((int(ranges[0].replace("X", digit)),
                     int(ranges[1].replace("X", digit)) + 1)
                     for digit in "0123456789")
    return any(number in range(*interval) for interval in actual_ranges)

結果:

>>> in_range(805001)
True
>>> in_range(895099)
True
>>> in_range(805100)
False

Paul McGuire によって提案された、これに対する改善 (ありがとう!):

def in_range(number, ranges=("8X5000", "8X5099")):
    actual_ranges = ((int(ranges[0].replace("X", digit)),
                     int(ranges[1].replace("X", digit)))
                     for digit in "0123456789")
    return any(minval <= number <= maxval for minval, maxval in actual_ranges)
于 2012-11-28T07:04:55.433 に答える