2016-08-09 12 views
-3

Ich bin auf der Suche nach einem Weg für find_equivalent() Proportionierungsmethode in den meisten Pythonic Weg.Was ist der pythischste Weg, diese Dosierungsmethode zu verkürzen?

Wenn y die Nummer nicht im Bereich 0 - 2000 liegt, muss die Methode 0 zurückgegeben werden. Andernfalls sollte die Methode den Bereich y finden und die gleiche Zahl in den Bereich zurückgeben.

def find_equivalent(y): 
    if y <= 0 or y > 2000: 
     return 0 
    elif 0 < y <= 100: 
     if y in range(1, 34): 
      return 18 
     if y in range(34, 67): 
      return 17 
     if y in range(67, 101): 
      return 16 
    elif 100 < y <= 200: 
     if y in range(101, 134): 
      return 15 
     if y in range(134, 167): 
      return 14 
     if y in range(167, 201): 
      return 13 
    elif 200 < y <= 500: 
     if y in range(201, 301): 
      return 12 
     if y in range(301, 401): 
      return 11 
     if y in range(401, 501): 
      return 10 
    elif 500 < y <= 1000: 
     if y in range(501, 667): 
      return 9 
     if y in range(667, 834): 
      return 8 
     if y in range(834, 1001): 
      return 7 
    elif 1000 < y <= 2000: 
     if y in range(1001, 1334): 
      return 6 
     if y in range(1334, 1667): 
      return 5 
     if y in range(1667, 2001): 
      return 4 
    . 
    . 
    . 
+1

ich werde Sie einen Tippfehler gemacht zu übernehmen haben, und es sollte 'sein elif 500 miradulo

+1

Warum haben Sie all diese 'elif' Tests, wenn Sie dann' y' * noch einmal testen *? Sie können auch alle diese 'wenn y in range (...)' testet die oberste Ebene (mit 'elif' zu Kurzschluss) –

+0

@Mitch Sie haben Recht. Ich korrigierte den Tippfehler. Vielen Dank. –

Antwort

6

Sie können nur berechnen Ihre Zahlen:

if 0 < y <= 200: 
    return 18 - ((y - 1) // 33) 
elif 200 < y <= 500: 
    return 12 - ((y - 201) // 100) 
elif 500 < y <= 1000: 
    return 9 - ((y - 501) // 667)) 
elif 1000 < y <= 2000: 
    return 6 - ((y - 501) // 1333) 
return 0 

und sogar jene Grenzwerte berechnet werden kann; sie sind auf dem Bereich basiert, dividiert durch 3.

Sie könnten die meisten dieser in eine Liste setzen und bisection verwenden die richtigen Grenzen zu finden:

from bisect import bisect_left 

boundaries = [0, 100, 200, 500, 1000, 2000] 

def find_equivalent(y): 
    if not 0 < y <= 2000: 
     return 0 

    index = bisect_left(boundaries, y) 
    stepsize = (boundaries[index] - boundaries[index - 1]) // 3 
    return 21 - (index * 3) - ((y - boundaries[index - 1] - 1) // stepsize) 

oder vorher berechnen die kleineren Bereichsgrenzen, aber immer noch verwenden bisection:

boundaries = [0, 100, 200, 500, 1000, 2000] 
precise_boundaries = [ 
    upper - ((upper - boundaries[i]) // 3 * step) 
    for i, upper in enumerate(boundaries[1:]) 
    for step in range(2, -1, -1)] 

def find_equivalent(y): 
    if not 0 < y <= 2000: 
     return 0 
    return 18 - bisect_left(precise_boundaries, y) 
+0

Mit * bisect * ist eine gute Lösung für * Nummer *. Was ist, wenn ich ** float ** benutze? –

+3

@SencerH .: Bisection funktioniert gut mit Fließkommazahlen, im Gegensatz zu Ihren 'y in range (...)' Tests. –

+0

Ich setze die Grenzen als '[0.0, 1.0, 2.0, 5.0, 10.0, 20.0]', aber wenn ich eine Fließkommazahl im Bereich zwischen * 0.1 * und * 1.9 * zur Methode gebe, gibt python einen ** ZeroDivisionError: float divmod() ** Fehler bei 'return 21 - (Index * 3) - ((y - Grenzen [index - 1] - 1) // Schrittweite)' Zeile wegen der 'Schrittweite' wird berechnet als * 0 * (Null). Wie soll ich dieses Problem lösen? –

0

Ich würde vorschlagen, zwei Listen zu verwenden, man die Werte für den Bereich und die andere enthält die Rückgabewerte, dh

rangelist = [0, 1, 34, 67, 100 (etc)] 
returnlist = [18, 17, 16 (etc)] 

Dann enthält der Eintrag von rangelist am nächsten zu Ihrem finden y und wählen Sie den passenden Artikel aus returnlist.

Verwandte Themen