while over for every array python numpy iteration range

over - ¿Hay un equivalente de Python de rango(n) para rangos multidimensionales?



python matrix iteration (7)

En Python, el rango (3) devolverá [0,1,2]. ¿Hay un equivalente para rangos multidimensionales?

range((3,2)) # [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]

Entonces, por ejemplo, si se repiten las baldosas de un área rectangular en un juego basado en fichas, se puede escribir como:

for x,y in range((3,2)):

Tenga en cuenta que no estoy pidiendo una implementación. Me gustaría saber si este es un patrón reconocido y si hay una función incorporada en Python o sus bibliotecas estándar / comunes.


En numpy, es numpy.ndindex . También eche un vistazo a numpy.ndenumerate .

P.ej

import numpy as np for x, y in np.ndindex((3,2)): print x, y

Esto produce:

0 0 0 1 1 0 1 1 2 0 2 1


En realidad hay una sintaxis simple para esto. Solo necesitas tener dos for s:

>>> [(x,y) for x in range(3) for y in range(2)] [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]


Ese es el producto cartesiano de dos listas, por lo tanto:

import itertools for element in itertools.product(range(3),range(2)): print element

da esta salida:

(0, 0) (0, 1) (1, 0) (1, 1) (2, 0) (2, 1)


Numpy''s ndindex() funciona para el ejemplo que proporcionó, pero no sirve para todos los casos de uso. A diferencia del range() incorporado de Python range() , que permite un start , una stop y un step arbitrarios, np.ndindex() de np.ndindex() solo acepta una stop . (Se supone que el start es (0,0,...) y el step es (1,1,...) .

Aquí hay una implementación que actúa más como la función range() incorporada. Es decir, permite arbitrarios argumentos de start / stop / step , pero funciona en tuplas en lugar de meros enteros.

import sys from itertools import product, starmap # Python 2/3 compatibility if sys.version_info.major < 3: from itertools import izip else: izip = zip xrange = range def ndrange(start, stop=None, step=None): if stop is None: stop = start start = (0,)*len(stop) if step is None: step = (1,)*len(stop) assert len(start) == len(stop) == len(step) for index in product(*starmap(xrange, izip(start, stop, step))): yield index

Ejemplo:

In [7]: for index in ndrange((1,2,3), (10,20,30), step=(5,10,15)): ...: print(index) ...: (1, 2, 3) (1, 2, 18) (1, 12, 3) (1, 12, 18) (6, 2, 3) (6, 2, 18) (6, 12, 3) (6, 12, 18)


Puede usar itertools.product() :

>>> import itertools >>> for (i,j,k) in itertools.product(xrange(3),xrange(3),xrange(3)): ... print i,j,k

Las múltiples declaraciones de xrange() repetidas podrían expresarse así, si quieres escalar esto hasta un bucle de diez dimensiones o algo similarmente ridículo:

>>> for combination in itertools.product( xrange(3), repeat=10 ): ... print combination

Que recorre más de diez variables, que varían desde (0,0,0,0,0,0,0,0,0,0) a (2,2,2,2,2,2,2,2,2,2)

En general, itertools es un módulo increíblemente increíble. Del mismo modo, las expresiones regulares son mucho más expresivas que los métodos de cadenas "simples", itertools es una forma muy elegante de expresar bucles complejos. Te debes a ti mismo leer la documentación del módulo itertools . Hará tu vida más divertida.


Puede usar el product del módulo itertools .

itertools.product(range(3), range(2))


numpy.meshgrid un vistazo a numpy.meshgrid :

http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.meshgrid.html

que le dará los valores de la grilla X e Y en cada posición en una malla / grilla. Entonces podrías hacer algo como:

import numpy as np X,Y = np.meshgrid(xrange(3),xrange(2)) zip(X.ravel(),Y.ravel()) #[(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1)]

o

zip(X.ravel(order=''F''),Y.ravel(order=''F'')) # [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]