El siguiente código de Python parece ser muy largo cuando proviene de un fondo de Matlab
>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]
Cuando en Matlab puedo escribir:
>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
3 6
¿Existe un método de mano corta para escribir esto en Python, o simplemente me quedo con la versión larga?
Gracias por todas las sugerencias y explicaciones del fundamento de la sintaxis de Python.
Después de encontrar lo siguiente en el sitio web de numpy, creo que encontré una solución que me gusta:
http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays
Aplicar la información de ese sitio web a mi problema anterior, daría lo siguiente:
>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]
Lo siguiente debería funcionar (pero no tengo un intérprete de Python a mano para probarlo):
class my_array(numpy.array):
def find(self, b):
r = array(range(len(b)))
return r(b)
>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]
[idx for idx in range(len(a)) if a[idx] > 2]
? La razón por la que esto es un poco incómodo de hacer en Python es porque no usa índices tanto como otros lenguajes.Respuestas:
En Python, no usarías índices para esto en absoluto, solo lidiarías con los valores—
[value for value in a if value > 2]
. Por lo general, tratar con índices significa que no está haciendo algo de la mejor manera.Si usted no necesita una API similar a Matlab, se usaría numpy , un paquete de matrices multidimensionales y matemáticas numérica en Python que está fuertemente inspirado en Matlab. Estaría usando una matriz numpy en lugar de una lista.
fuente
filtered_ranges_and_angles = [(range, angle) for range, angle in zip(ranges, angles) if should_be_kept(range)]
De otra manera:
En general, recuerde que si bien
find
es una función lista para usar, las listas por comprensión son una solución general y, por lo tanto, muy poderosa . Nada le impide escribir unafind
función en Python y usarla más tarde como desee. Es decir:Tenga en cuenta que estoy usando listas aquí para imitar Matlab. Sería más Pythonic usar generadores e iteradores.
fuente
[i for i,v in enumerate(a) if v > 2]
lugar.index
coni
yvalue
conv
en el original y cuente los caracteres.enumerate
overrange(len(...))
es más robusto y más eficiente.find_indices
función para usarenumerate
Para mi funciona bien:
fuente
Quizás otra pregunta sea, "¿qué vas a hacer con esos índices una vez que los obtengas?" Si los va a usar para crear otra lista, en Python, son un paso intermedio innecesario. Si desea que todos los valores coincidan con una condición determinada, simplemente use el filtro incorporado:
O escriba su propia lista de comprensión:
Si desea eliminarlos de la lista, entonces la forma Pythonic no es necesariamente eliminarlos de la lista, sino escribir una lista de comprensión como si estuviera creando una nueva lista y volviendo a asignar en el lugar usando el
listvar[:]
de la izquierda. -lado:Matlab suministra
find
porque su modelo centrado en matrices funciona seleccionando elementos utilizando sus índices de matriz. Usted puede hacer esto en Python, sin duda, pero la forma más Pythonic está utilizando iteradores y generadores, como ya se ha mencionado por @EliBendersky.fuente
a[:] = ...
, mira la respuesta de Alex Martelli a esta pregunta stackoverflow.com/questions/1352885/… .Incluso si es una respuesta tardía: creo que esta sigue siendo una muy buena pregunta y, en mi humilde opinión, Python (sin bibliotecas o kits de herramientas adicionales como numpy) todavía carece de un método conveniente para acceder a los índices de los elementos de la lista de acuerdo con un filtro definido manualmente.
Puede definir manualmente una función, que proporciona esa funcionalidad:
Rendimientos: [0, 4]
En mi imaginación, la manera perfecta sería hacer una lista de clase secundaria y agregar la función de índices como método de clase. De esta manera solo se necesitaría el método de filtro:
Elaboré un poco más sobre ese tema aquí: http://tinyurl.com/jajrr87
fuente