Ответ 1
В numpy, numpy.ndindex
. Также посмотрите numpy.ndenumerate
.
например.
import numpy as np
for x, y in np.ndindex((3,2)):
print x, y
Это дает:
0 0
0 1
1 0
1 1
2 0
2 1
В Python диапазон (3) вернет [0,1,2]. Существует ли эквивалент для многомерных диапазонов?
range((3,2)) # [(0,0),(0,1),(1,0),(1,1),(2,0),(2,1)]
Итак, например, цикл, хотя плитки прямоугольной области в игре на основе плитки могут быть записаны как:
for x,y in range((3,2)):
Примечание. Я не прошу реализации. Я хотел бы знать, является ли это признанным шаблоном, и если есть встроенная функция на Python или это стандартные/общие библиотеки.
В numpy, numpy.ndindex
. Также посмотрите numpy.ndenumerate
.
например.
import numpy as np
for x, y in np.ndindex((3,2)):
print x, y
Это дает:
0 0
0 1
1 0
1 1
2 0
2 1
Вы можете использовать itertools.product()
:
>>> import itertools
>>> for (i,j,k) in itertools.product(xrange(3),xrange(3),xrange(3)):
... print i,j,k
Несколько повторяющихся операторов xrange()
могут быть выражены так, если вы хотите масштабировать это до десятимерного цикла или что-то подобное смехотворное:
>>> for combination in itertools.product( xrange(3), repeat=10 ):
... print combination
Который перебирает десять переменных, варьируя от (0,0,0,0,0,0,0,0,0,0)
до (2,2,2,2,2,2,2,2,2,2)
.
В целом itertools
является безумно удивительным модулем. Точно так же регулярные выражения намного более выразительны, чем "простые" строковые методы, itertools
- очень элегантный способ выражения сложных циклов. Вы обязаны сделать это для себя, чтобы прочитать документацию модуля itertools
. Это сделает вашу жизнь более увлекательной.
На самом деле для этого существует простой синтаксис. Вам просто нужно иметь два 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)]
Таким образом, cartesian product из двух списков:
import itertools
for element in itertools.product(range(3),range(2)):
print element
дает этот результат:
(0, 0)
(0, 1)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
Вы можете использовать product
из модуля itertools
.
itertools.product(range(3), range(2))
Я бы посмотрел на numpy.meshgrid
:
http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.meshgrid.html
который даст вам значения X и Y сетки в каждой позиции сетки/сетки. Тогда вы можете сделать что-то вроде:
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)]
или
zip(X.ravel(order='F'),Y.ravel(order='F'))
# [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)]
Numpy ndindex()
работает для примера, который вы дали, но он не обслуживает все варианты использования. В отличие от встроенного Python range()
, который допускает как произвольные start
, stop
, так и step
, numpy np.ndindex()
принимает только stop
. (Предполагается, что start
(0,0,...)
, а step
- (1,1,...)
.)
Здесь реализована реализация, которая больше похожа на встроенную функцию range()
. То есть он допускает произвольные аргументы start
/stop
/step
, но он работает с кортежами вместо простых целых чисел.
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
Пример:
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)