Pregunta

Tengo el siguiente código:

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]

Básicamente, calcular un nuevo índice y el uso que para encontrar algún elemento de una lista. Con el fin de asegurarse de que el índice está dentro de los límites de la lista, que necesitaba escribir los estados 2 if difusión en 4 líneas. Eso es bastante detallado, un poco feo ... Me atrevo a decir, es bastante un-Pythonic .

Hay alguna otra solución más simple y más compacto? (y más Pythonic )

Sí, sé que puedo usar if else en una línea, pero no se puede leer:

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

También sé que puedo max() cadena y min() juntos. Es más compacto, pero siento que es un poco oscura, más difíciles de encontrar errores si escribo mal. En otras palabras, no me parece que sea muy sencillo.

new_index = max(0, min(new_index, len(mylist)-1))
¿Fue útil?

Solución

Esto es bastante claro, en realidad. Muchas personas aprenden rápidamente. Se puede utilizar un comentario para ayudarlos.

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

Otros consejos

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

por ejemplo:

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

muchas respuestas interesantes aquí, todo sobre el mismo, excepto ... ¿cuál es más rápido?

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 lo tiene !, utilizar ol llano' pitón. La versión numpy es, tal vez no es sorprendente que el más lento de todos. Probablemente porque está buscando matrices, donde las otras versiones orden justo sus argumentos.

El encadenamiento max() y min() juntos es el lenguaje normal, que he visto. Si le resulta difícil de leer, escribir una función auxiliar para encapsular la operación:

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

¿Qué pasó con mi lenguaje Python legible amada? : -)

En serio, sólo hacen que sea una función:

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

a continuación, sólo lo llaman con algo como:

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

O un simple, más flexible, solución en la que lo hace el cálculo usted mismo:

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

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

Si quisiera, podría incluso hacer la lista un mínimo / máximo para que se vea más "matemáticamente puro":

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

Éste parece más a mí Pythonic:

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

Algunas pruebas:

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

Si su código parece demasiado difícil de manejar, una ayuda podría funcionar:

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

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

evitar la escritura de funciones para este tipo de tareas pequeñas, a menos que se las aplica a menudo, ya que el desorden de su código.

para valores individuales:

min(clamp_max, max(clamp_min, value))

para listas de valores:

map(lambda x: min(clamp_max, max(clamp_min, x)), values)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top