2013-02-16 4 views
5

Problem:Jak stosować Max & granice min do wartości bez użycia instrukcji warunkowych

Napisz funkcję Pythona, klips (LO, X, hi), która zwraca lo jeśli x jest mniejsze niż LO; hi jeśli x jest większe niż hi; i x inaczej. W tym przypadku możesz założyć, że lo < hi.

Nie używaj żadnych instrukcji warunkowych dla tego problemu. Zamiast tego użyj wbudowanych funkcji Pythona min i max. Możesz chcieć przeczytać dokumentację na temat min i dokumentację na maksa, i trochę pogadać z tymi funkcjami w swoim tłumaczu, zanim zaczniesz ten problem.

Ta funkcja przyjmuje trzy liczby i zwraca pojedynczą liczbę.

Kod Dane:

def clip(lo, x, hi): 
    ''' 
    Takes in three numbers and returns a value based on the value of x. 
    Returns: 
    - lo, when x < lo 
    - hi, when x > hi 
    - x, otherwise 
    ''' 

mojego kodu Dodano:

def clip(lo, x, hi): 
    ''' 
    Takes in three numbers and returns a value based on the value of x. 
    Returns: 
    - lo, when x < lo 
    - hi, when x > hi 
    - x, otherwise 
    ''' 
    if min(x, lo, hi) == x: 
     return lo 
    elif max(x, lo, hi) == x: 
     return hi 
    else: 
     return x 

Oto problem: Nie mogę korzystać ŻADNYCH warunkowe. Wsparcie!

+1

Rozgrywaj połączenia na maks. I min. –

+0

@AdamVandenberg Co to znaczy? – user2066771

+1

@ user2066771: Oznacza to nawiązywanie połączenia między sobą. – martineau

Odpowiedz

7

Masz wiele opcji do tej pory proponowanych. jeszcze nie pisał jest zagnieżdżona trójskładnikowych wyrażenie:

def clip(lo, x, hi): 
    return lo if x <= lo else hi if x >= hi else x 

Ale ponieważ używa jawnych testy warunkowe, prawdopodobnie nie nadaje się jako rozwiązanie do pierwotnego pytania. Mimo to, biorąc pod uwagę te opcje, jest to ta, która ma zalety zwarcia, jeśli x <= lo (wszystkie inne metody oceniają wszystkie porównania i/lub wykonują jedno lub dwa wywołania metod). Zobaczmy, w jaki sposób te alternatywy wykonują za pomocą timeit (testowane z Pythona 3.3, więc zasięg nie zbudować listę, ale zwraca iterator):

python -m timeit -s "lo,hi=10,90" "[max(lo,min(hi,x)) for x in range(100)]" 
10000 loops, best of 3: 54.5 usec per loop 

(2 wywołania funkcji za oceny, zabija wydajność)

python -m timeit -s "lo,hi=10,90" "[(lo,(hi,x)[x<hi])[x>lo] for x in range(100)]" 
10000 loops, best of 3: 40.9 usec per loop 

(ocenia oba testy i buduje krotki dla każdej oceny, ale przynajmniej nie ma wywołania funkcji)

python -m timeit -s "lo,hi=10,90" "[sorted((lo,x,hi))[1] for x in range(100)]" 
10000 loops, best of 3: 90.5 usec per loop 

(buduje krotki i sortuje - Przepraszam, Gnibbler, to najwolniejszy)

python -m timeit -s "lo,hi=10,90" "[lo if x <= lo else hi if x >= hi else x for x in range(100)]" 
100000 loops, best of 3: 18.9 usec per loop 

(najszybciej, bez wywołania funkcji, tylko ocenia x >= hi jeśli x > lo)

to zwarcie widać po przeniesieniu wartość lo znacznie wyższe w zakresie testu:

python -m timeit -s "lo,hi=80,90" "[lo if x <= lo else hi if x >= hi else x for x in range(100)]" 
100000 loops, best of 3: 15.1 usec per loop 

(Jeśli chcesz, aby odtworzyć te pod Pythona 2.x, wymienić range z xrange.)

+0

Lepiej po prostu umieść 'L = zasięg (100)' w konfiguracji, ponieważ nie modyfikujesz tego. –

+0

Niektórzy mogą powiedzieć wyrażenie trójdzielne jest jednak warunkowe. –

+0

Zgadzam się, stąd mój komentarz "Ale ponieważ używa to jednoznacznych testów warunkowych, prawdopodobnie nie nadaje się jako rozwiązanie pierwotnego pytania." I ciekawa rzecz: bałem się, że wprowadzenie 'L = range (100)' w konfiguracji byłoby problemem, ponieważ używam języka Python 3.3, w którym 'range' zwraca iterator, który zostałby zużyty w pierwszym teście uruchom, ale potem pozostań pusty dla wszystkich następnych testów. Okazało się, że tak nie jest, więc najwyraźniej kod instalacyjny jest wywoływany przed każdym uruchomieniem testowym, po prostu nie jest uwzględniony w statystykach synchronizacji (lub mógłbym tylko ustawić 'L = list (zakres (100)).)) – PaulMcG

3

Bez wydawania całego rozwiązania - nie trzeba niczego "sprawdzać". Wartość od lo od dołu to wartość uzyskana z uruchomienia max(x, lo).

Również wartość przycięta do jednej granicy nie zostanie zakłócona przez obcięcie do drugiej granicy, więc można bezpiecznie uruchomić wynik jednej korekty za pomocą innej.

8

Oto rozwiązanie, zakładając, że lo < cześć.

def clip(lo, x, hi): 
    return max(lo, min(hi, x)) 

Jak to działa w każdym przypadku:

  • lo, gdy x < lo: jeśli lo < hi, to x < hi, więc min(hi, x) powraca x i max(lo, x) powraca lo.
  • cześć, gdy x> hi: min(hi, x) powraca hi i jeśli lo < hi, max(lo, hi) powraca hi
  • X, w przeciwnym razie: x> lo x < HI, tak min(hi, x) zwraca x i max(lo, x) powraca x
0
def clip(lo, x, hi): 
    return sorted((lo, x, hi))[1] 
+0

Sprytna, ale powolna - zobacz moje odmierzanie czasu – PaulMcG

1

Inne rozwiązanie:

def clip(lo, x, hi): 
    result = {x: x} 
    result[min(x, lo)] = lo 
    result[max(x, hi)] = hi 
    return result[x] 
0

min? max?Co powiesz na:

def clip(lo,x,hi): 
    return (lo,(hi,x)[x<hi])[x>lo] 
-2

tu również rozwiązanie: powrotu min (max (x, LO), HI)

+4

To jest po prostu odwrotnością odpowiedzi Nicolasa. Co to dodaje? – EWit

1

rozwiązanie:

def clip(lo, x, hi): 
    x = max(lo, x) 
    x = min(x, hi) 
    return x 
0

to załatwi bez operatorów warunkowych.

max(lo,min(hi,x)) 
Powiązane problemy