2010-09-08 22 views
10

Ho una funzione che ha passato due valori e quindi scorre sull'intervallo di quei valori. I valori possono essere passati in qualsiasi ordine, quindi ho bisogno di trovare quale è il più basso per primo. Ho avuto la funzione scritta in questo modo:Il modo migliore per trovare il massimo e il minimo di due valori

def myFunc(x, y): 
    if x > y: 
     min_val, max_val = y, x 
    else: 
     min_val, max_val = x, y 
    for i in range(min_val, max_val): 
    ... 

Ma per risparmiare un po 'di spazio schermo, ho finito per cambiarlo a:

def myFunc(x, y): 
    min_val, max_val = sorted([x, y]) 
    for i in range(min_val, max_val): 
    ... 

Quanto è grave questa? C'è un modo migliore che è ancora una linea?

risposta

4

A meno che non avete bisogno di microoptimise, mi piacerebbe proprio a questa

def myFunc(x, y): 
    for i in range(*sorted((x, y))): 
     ... 

Questo è più veloce anche se

def myFunc(x, y): 
    for i in range(x,y) if x<y else range(y,x): 
     ... 

minmax.py

def f1(x, y): 
    for i in range(min(x, y), max(x, y)): 
     pass 

def f2(x, y): 
    for i in range(*sorted((x, y))): 
     pass 

def f3(x, y): 
    for i in range(x, y) if x<y else range(y, x): 
     pass 

def f4(x, y): 
    if x>y: 
     x,y = y,x 
    for i in range(x, y): 
     pass 

def f5(x, y): 
    mn,mx = ((x, y), (y, x))[x>y] 
    for i in range(x,y): 
     pass 

parametri di riferimento ( f3 è il più veloce r egardless dell'ordine)

$ python -m timeit -s"import minmax as mm" "mm.f1(1,2)" 
1000000 loops, best of 3: 1.93 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f2(1,2)" 
100000 loops, best of 3: 2.4 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f3(1,2)" 
1000000 loops, best of 3: 1.16 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f4(1,2)" 
100000 loops, best of 3: 1.2 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f5(1,2)" 
1000000 loops, best of 3: 1.58 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f1(2,1)" 
100000 loops, best of 3: 1.88 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f2(2,1)" 
100000 loops, best of 3: 2.39 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f3(2,1)" 
1000000 loops, best of 3: 1.18 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f4(2,1)" 
1000000 loops, best of 3: 1.25 usec per loop 
$ python -m timeit -s"import minmax as mm" "mm.f5(2,1)" 
1000000 loops, best of 3: 1.44 usec per loop 
15

min e max sono i tuoi amici.

def myFunc(x, y): 
    min_val, max_val = min(x, y), max(x, y) 

Modifica. Benchmark versione min-max againt un semplice if. A causa della funzione chiamata overhead, min-max richiede più che il semplice if; vedi http://gist.github.com/571049

+0

non avevo nemmeno pensato di fare che in una riga. Ma a seconda della modalità di implementazione, potrebbe essere effettivamente meno efficiente. So che l'ordinamento della libreria standard in C++ è hardcoded per <7 elementi, quindi l'ordinamento di una lista di due elementi sarebbe solo un confronto singolo. C'è però il costo aggiuntivo della creazione di un oggetto lista. – Colin

4

Mi piace lo sorted. Intelligente ma non troppo intelligente. Ecco alcune altre opzioni.

def myFunc(min, max): 
    if min > max: min, max = max, min 

def myFunc(x, y): 
    min, max = min(x, y), max(x, y) 

def myFunc(x, y): 
    min, max = [f(x, y) for f in (min, max)] 

L'ultimo è un po 'sciocco lo ammetto.

+2

È meglio utilizzare altri nomi oltre a min e max, poiché sono incorporati in Python. –

1

Alcuni suggerimenti

def myfunc(minVal, maxVal): 
    if minVal > maxVal: minVal, maxVal = maxVal, minVal 

def myfunc2(a, b): 
    minVal, maxVal = ((a, b), (b, a))[a > b] # :-P 

Uso ordinati, i min/max comandi incorporati o la seconda soluzione di cui sopra sembra eccessivo in questo caso.

E ricorda che range(min, max) itererà da min a max - 1!

2

La migliore risposta singola funziona come:

def foo(lo, hi): 
    if hi < lo: lo,hi = hi,lo 

E 'chiaro, fa un punto, e non lo fa significato oscuro un po' di colla supplementare. È breve. È quasi certamente veloce come qualsiasi altra opzione nella pratica, e si basa sulla minima quantità di intelligenza.

4

Dal domanda del PO è stata posta utilizzando x e y come parametri (non lo e hi), vorrei andare con (sia per la velocità e chiarezza):

def myfunc(x, y): 
    lo, hi = (x, y) if x < y else (y, x) 

>>> timeit.repeat("myfunc(10, 5)", "from __main__ import myfunc") 
[1.2527812156004074, 1.185214249195269, 1.1886092749118689] 
>>> timeit.repeat("foo(10, 5)", "from __main__ import foo") 
[1.0397177348022524, 0.9580022495574667, 0.9673979369035806] 
>>> timeit.repeat("f3(10, 5)", "from __main__ import f3") 
[2.47303065772212, 2.4192818561823515, 2.4132735135754046] 
+0

buon uso di decompressione, questa risposta mi piace di più – timgeb

Problemi correlati