Question

Je le code suivant:

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]

En fait, je calculer un nouvel indice et l'utiliser pour trouver un élément dans une liste. Afin de vous assurer que l'indice est à l'intérieur des limites de la liste, je devais écrire ces 2 déclarations if diffusion en 4 lignes. C'est tout à fait bavard, un peu moche ... oserais-je dire, il est tout à fait non pythonique .

Est-il une autre solution plus simple et plus compact? (et plus pythonique )

Oui, je sais que je peux utiliser if else en une ligne, mais il est pas lisible:

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

Je sais aussi que je peux chaîne max() et min() ensemble. Il est plus compact, mais je pense qu'il est un peu obscurcir, plus difficile de trouver des bugs si je tape mal. En d'autres termes, je ne trouve pas très simple.

new_index = max(0, min(new_index, len(mylist)-1))
Était-ce utile?

La solution

Ceci est assez clair, en fait. Beaucoup de gens apprennent rapidement. Vous pouvez utiliser un commentaire pour les aider.

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

Autres conseils

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

par exemple:

>>> 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

Voir numpy.clip :

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

de nombreuses réponses intéressantes ici, tous sur le même, sauf ... que l'on est plus rapide?

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 a it !, utiliser plaine ol » python. La version numpy est, peut-être sans surprise, le plus lent du lot. Probablement parce qu'il cherche des tableaux, où les autres versions ordre juste leurs arguments.

Enchaînement max() et min() ensemble est l'idiome normale que j'ai vu. Si vous avez du mal à lire, écrire une fonction d'assistance pour encapsuler l'opération:

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

Qu'est-il arrivé à mon bien-aimé lisible langage Python? : -)

Sérieusement, il suffit de faire une fonction:

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

alors il suffit d'appeler avec quelque chose comme:

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

Ou un simple, plus flexible, solution où vous faites le calcul vous-même:

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

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

Si vous voulez, vous pouvez même faire le min / max liste de sorte qu'il semble plus « mathématiquement pure »:

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

Celui-ci me semble plus pythonique à:

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

Quelques tests:

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

Si votre code semble trop difficile à manier, une fonction pourrait aider:

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

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

Évitez d'écrire des fonctions pour ces petites tâches, à moins que vous les appliquez souvent, car il encombrer votre code.

pour les valeurs individuelles:

min(clamp_max, max(clamp_min, value))

pour les listes de valeurs:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top