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()
ステートメントの繰り返しは、10次元のループまたは同様に馬鹿げたものにスケールアップしたい場合は、次のように表現できます。
_>>> 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)
_まで、10個の変数をループします。
一般的にitertools
はめちゃくちゃ素晴らしいモジュールです。正規表現が「プレーンな」文字列メソッドよりもはるかに表現力が高いのと同じように、itertools
は複雑なループを表現する非常にエレガントな方法です。 itertools
モジュールのドキュメントを読むのはあなた自身の責任です これはあなたの人生をより楽しくします。
これには実際には簡単な構文があります。 2つの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)]
つまり、2つのリストの デカルト積 です。
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()
は、指定した例では機能しますが、すべてのユースケースに対応しているわけではありません。任意のstart
、stop
、およびstep
の両方を許可するPythonの組み込みrange()
とは異なり、numpyのnp.ndindex()
は、 stop
。 (start
は_(0,0,...)
_であると推定され、step
は_(1,1,...)
_です。)
これは、組み込みのrange()
関数のように機能する実装です。つまり、任意のstart
/stop
/step
引数を許可しますが、単なる整数の代わりにtuplesで機能します。
_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)
_