在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中是否有內置函數或它是標準/通用庫。
在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中是否有內置函數或它是標準/通用庫。
在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
實際上這是一個簡單的語法。你只需要兩個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)]
這是一件好事,但我想指出,它可以得到一個有點冗長:在[(X,Y) 爲(X,Y)在X範圍(3)爲範圍(2)中的y]: – MaiaVictor 2012-04-10 17:34:28
你可以使用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.它會讓你的生活更有趣。
對您的上一個答案只是一個很小的改進: 對於產品中的c(*([xrange(5)] * 3)):print c':from(0 ,0,0)到(4,4,4) – egor83 2012-04-10 17:27:47
如果你想要精確的副本,使用'itertools.tee()'實際上更好 - 我相信由於緩存,底層實現更高效。 – 2012-04-10 17:29:21
@ egor83/Li-aung Yip:在提出複雜的解決方案之前,請閱讀'itertools'文檔。它是'itertools.product(xrange(3),repeat = 3)'。 – agf 2012-04-10 17:35:32
您可以使用product
從itertools
模塊。
itertools.product(range(3), range(2))
也就是說因此兩個列表的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)
我會看看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.mgrid'和'numpy.ogrid'。 – 2012-04-10 19:07:22
與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)
正好趕上衝刺! – MaiaVictor 2017-09-21 01:16:27
+1:其語法與OP最初要求的語法非常相似。打的好! – 2012-04-11 00:16:03
正如李昂所指出的,這與我所要求的驚人地相似,所以無疑是這個話題的最佳答案。 – MaiaVictor 2012-04-14 15:33:32
Li-aung Yip的答案也很棒,並且有一些學習,因爲它表明笛卡爾產品可以用於相同的目的。 – MaiaVictor 2012-11-16 00:31:32