2012-04-10 78 views
40

在Python上,范围(3)将返回[0,1,2]。有多维范围的等价物吗?对于多维范围,是否有Python的等价范围(n)?

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

注意我不是要求实现:

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

因此,例如,循环虽然在基于区块的游戏中的矩形区域的瓷砖,可以书面。我想知道这是否是一种公认​​的模式,以及Python中是否有内置函数或它是标准/通用库。

回答

50

在numpy的,它是numpy.ndindex。也看看numpy.ndenumerate

E.g.

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 
+4

+1:其语法与OP最初要求的语法非常相似。打的好! – 2012-04-11 00:16:03

+0

正如李昂所指出的,这与我所要求的惊人地相似,所以无疑是这个话题的最佳答案。 – MaiaVictor 2012-04-14 15:33:32

+1

Li-aung Yip的答案也很棒,并且有一些学习,因为它表明笛卡尔产品可以用于相同的目的。 – MaiaVictor 2012-11-16 00:31:32

22

实际上这是一个简单的语法。你只需要两个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)] 
+0

这是一件好事,但我想指出,它可以得到一个有点冗长:在[(X,Y) 为(X,Y)在X范围(3)为范围(2)中的y]: – MaiaVictor 2012-04-10 17:34:28

35

你可以使用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是一种表达复杂循环的非常优雅的方式。 You owe it to yourself to read the itertools module documentation.它会让你的生活更有趣。

+0

对您的上一个答案只是一个很小的改进: 对于产品中的c(*([xrange(5)] * 3)):print c':from(0 ,0,0)到(4,4,4) – egor83 2012-04-10 17:27:47

+0

如果你想要精确的副本,使用'itertools.tee()'实际上更好 - 我相信由于缓存,底层实现更高效。 – 2012-04-10 17:29:21

+0

@ egor83/Li-aung Yip:在提出复杂的解决方案之前,请阅读'itertools'文档。它是'itertools.product(xrange(3),repeat = 3)'。 – agf 2012-04-10 17:35:32

3

您可以使用productitertools模块。

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

也就是说因此两个列表的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) 
3

我会看看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)] 
+0

在这里也可以提到'numpy.mgrid'和'numpy.ogrid'。 – 2012-04-10 19:07:22

1

与NumPy的ndindex()作品你给的例子,但它不会成为所有用例。与Python的内置range()不同,它允许任意start,stopstep,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) 
+0

正好赶上冲刺! – MaiaVictor 2017-09-21 01:16:27