112 votes

Comment fixer un entier à une certaine plage? (en Python)

J'ai 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]

Fondamentalement, je calcule un nouvel indice et l'utiliser pour trouver un élément dans une liste. Afin de garantir que l'index est à l'intérieur des limites de la liste, j'avais besoin d'écrire ces 2 if états répartis en 4 lignes. C'est très bavard, un peu moche... si j'Ose dire, c'est assez onu-pythonic.

Est-il un autre plus simple et plus compact solution? (et plus pythonic)

Oui, je sais que je peux utiliser if else en une seule ligne, mais il n'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 de la chaîne d' max() et min() ensemble. Il est plus compact, mais je pense qu'il est un peu obscur, de plus en plus difficile de trouver des bugs si je tape mal. En d'autres termes, je ne trouve pas ça très simple.

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

139voto

S.Lott Points 207588

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

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

103voto

gnibbler Points 103484
 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
 

48voto

IfLoop Points 59461

beaucoup de réponses intéressantes ici, toutes à peu près les mêmes, sauf que ... lequel est le 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 l' a!, utilisez un vieux python. La version numpy est, peut-être sans surprise, la plus lente du lot. Probablement parce qu'il recherche des tableaux, où les autres versions ordonnent simplement leurs arguments.

40voto

Neil G Points 7028

Voir numpy.clip :

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

21voto

Laurence Gonsalves Points 50783

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

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X