Domanda

Ho il seguente codice:

new_index = index + offset
if new_index < 0:
    new_index = 0
if new_index >= len(mylist):
    new_index = len(mylist) - 1
return mylist[new_index]

In sostanza, ho calcolare un nuovo indice e l'uso che per trovare qualche elemento da un elenco. Al fine di assicurarsi che l'indice è all'interno dei limiti della lista, avevo bisogno di scrivere quei 2 if dichiarazioni diffuse in 4 linee. Questo è abbastanza prolisso, un po 'brutto ... oserei dire, è abbastanza non-divinatorio .

C'è qualche altra soluzione più semplice e più compatto? (e più divinatorio )

Sì, so che posso utilizzare if else in una sola riga, ma non è leggibile:

new_index = 0 if new_index < 0 else len(mylist) - 1 if new_index >= len(mylist) else new_index

so anche che posso catena max() e min() insieme. E 'più compatta, ma sento che è un pò oscuro, più difficile da trovare bug se di tipo sbagliato. In altre parole, non mi trovo molto semplice.

new_index = max(0, min(new_index, len(mylist)-1))
È stato utile?

Soluzione

Questo è abbastanza chiaro, in realtà. Molte persone imparano in fretta. È possibile utilizzare un commento per aiutarli.

new_index = max(0, min(new_index, len(mylist)-1))

Altri suggerimenti

sorted((minval, value, maxval))[1]

Ad esempio:

>>> minval=3
>>> maxval=7
>>> for value in range(10):
...   print sorted((minval, value, maxval))[1]
... 
3
3
3
3
4
5
6
7
7
7

numpy.clip :

index = numpy.clip(index, 0, len(my_list) - 1)

molte risposte interessanti qui, tutti circa lo stesso, tranne ... che uno è più veloce?

import numpy
np_clip = numpy.clip
mm_clip = lambda x, l, u: max(l, min(u, x))
s_clip = lambda x, l, u: sorted((x, l, u))[1]
py_clip = lambda x, l, u: l if x < l else u if x > u else x
>>> import random
>>> rrange = random.randrange
>>> %timeit mm_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 1.02 µs per loop

>>> %timeit s_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 1.21 µs per loop

>>> %timeit np_clip(rrange(100), 10, 90)
100000 loops, best of 3: 6.12 µs per loop

>>> %timeit py_clip(rrange(100), 10, 90)
1000000 loops, best of 3: 783 ns per loop

paxdiablo ha It !, utilizzare pianura ol' pitone. La versione NumPy è, forse non a caso, il più lento del lotto. Probabilmente perché è alla ricerca di matrici, in cui le altre versioni giusto ordine i loro argomenti.

Chaining max() e min() insieme è il linguaggio normale che ho visto. Se si fatica a leggere, scrivere una funzione di supporto per incapsulare l'operazione:

def clamp(minimum, x, maximum):
    return max(minimum, min(x, maximum))

Cosa è successo al mio amato linguaggio leggibile Python? : -)

Scherzi a parte, appena ne fanno una funzione:

def addInRange(val, add, minval, maxval):
    newval = val + add
    if newval < minval: return minval
    if newval > maxval: return maxval
    return newval

allora lo chiamano semplicemente con qualcosa di simile:

val = addInRange(val, 7, 0, 42)

O un più semplice, più flessibile, soluzione in cui si fa il calcolo da soli:

def restrict(val, minval, maxval):
    if val < minval: return minval
    if val > maxval: return maxval
    return val

x = restrict(x+10, 0, 42)

Se si volesse, si potrebbe anche fare l'/ lista un massimo minimo in modo che appaia più "matematicamente pura":

x = restrict(val+7, [0, 42])

Questo sembra più divinatorio a me:

>>> def clip(val, min_, max_):
...     return min_ if val < min_ else max_ if val > max_ else val

Alcuni test:

>>> clip(5, 2, 7)
5
>>> clip(1, 2, 7)
2
>>> clip(8, 2, 7)
7

Se il codice sembra troppo ingombrante, un aiuto funzione potrebbe:

def clamp(minvalue, value, maxvalue):
    return max(minvalue, min(value, maxvalue))

new_index = clamp(0, new_index, len(mylist)-1)

funzioni di scrittura per questi piccoli compiti, a meno che non li applicano spesso, come sarà ingombrare il codice. Evitare

per i valori individuali:

min(clamp_max, max(clamp_min, value))

per gli elenchi di valori:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top