在 Python 上,range(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)]
因此,这是两个列表的笛卡尔积:
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)]
Numpyndindex()
适用于您提供的示例,但并不适用于所有用例。与 Python 的内置range()
, 允许任意start
的stop
, 和不同step
,numpynp.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)