2012-04-10 36 views
40

Trên Python, phạm vi (3) sẽ trả về [0,1,2]. Có tương đương với các phạm vi đa chiều không?Có một phạm vi tương đương Python (n) cho các phạm vi đa chiều không?

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

Vì vậy, ví dụ, Looping dù gạch của một khu vực hình chữ nhật trên một trò chơi gạch dựa trên có thể được viết như sau:

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

Note Tôi không yêu cầu cho việc thực hiện. Tôi muốn biết nếu đây là một mẫu được công nhận và nếu có một hàm dựng sẵn trên Python hoặc nó là các thư viện chuẩn/phổ biến.

Trả lời

50

Trong NumPy, nó numpy.ndindex. Ngoài ra, hãy xem numpy.ndenumerate.

Ví dụ:

import numpy as np 
for x, y in np.ndindex((3,2)): 
    print x, y 

sản lượng này:

0 0 
0 1 
1 0 
1 1 
2 0 
2 1 
+4

+1: Cú pháp cho điều đó tương tự đáng báo động với những gì OP ban đầu được yêu cầu. Vâng chơi! –

+0

Vì Li-aung đã chỉ ra điều này khá giống với những gì tôi yêu cầu, nên chắc chắn đó là câu trả lời hay nhất cho chủ đề. – MaiaVictor

+1

Câu trả lời của Li-aung Yip cũng rất tuyệt, và có một số học hỏi về nó vì nó cho thấy sản phẩm Descartes có thể được sử dụng cho cùng một mục đích. – MaiaVictor

22

Có một cú pháp đơn giản cho việc này. Bạn chỉ cần có hai 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

này là tốt, nhưng tôi muốn chỉ rằng nó có thể nhận được một chút chi tiết: cho (x, y) trong [(x, y) cho x trong phạm vi (3) cho y trong phạm vi (2)]: – MaiaVictor

35

Bạn có thể sử dụng itertools.product():

>>> import itertools 
>>> for (i,j,k) in itertools.product(xrange(3),xrange(3),xrange(3)): 
...  print i,j,k 

Bội lặp đi lặp lại xrange() báo cáo có thể được thể hiện như vậy, nếu bạn muốn mở rộng này lên đến một ten- vòng lặp chiều hoặc thứ gì đó tương tự vô lý:

>>> for combination in itertools.product(xrange(3), repeat=10): 
...  print combination 

Vòng lặp nào có trên 10 biến, thay đổi từ (0,0,0,0,0,0,0,0,0,0) đến (2,2,2,2,2,2,2,2,2,2).


Nói chung itertools là một mô-đun cực kỳ tuyệt vời. Trong cùng một cách regexps là nhiều hơn nữa biểu cảm hơn "đồng bằng" chuỗi phương pháp, itertools là một cách rất thanh lịch của thể hiện các vòng phức tạp. You owe it to yourself to read the itertools module documentation. Nó sẽ làm cho cuộc sống của bạn thú vị hơn.

+0

chỉ là một cải tiến nhỏ so với câu trả lời cuối cùng của bạn: 'cho c trong sản phẩm (* ([xrange (5)] * 3)): in c': from (0 , 0,0) đến (4,4,4) – egor83

+0

Nó thực sự tốt hơn để sử dụng 'itertools.tee()' nếu bạn muốn bản sao chính xác - tôi tin rằng việc triển khai cơ bản là hiệu quả hơn do bộ nhớ đệm. –

+0

@ egor83/Li-aung Yip: Vui lòng đọc tài liệu 'itertools' trước khi đề xuất các giải pháp phức tạp. Đó là 'itertools.product (xrange (3), repeat = 3)'. – agf

3

Bạn có thể sử dụng product từ mô-đun itertools.

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

Đó là cartesian product của hai danh sách vì thế:

import itertools 
for element in itertools.product(range(3),range(2)): 
    print element 

cho sản lượng này:

(0, 0) 
(0, 1) 
(1, 0) 
(1, 1) 
(2, 0) 
(2, 1) 
3

tôi sẽ có một cái nhìn tại numpy.meshgrid:

http://docs.scipy.org/doc/numpy-1.6.0/reference/generated/numpy.meshgrid.html

sẽ cung cấp cho bạn giá trị lưới X và Y ở mỗi vị trí trong lưới/lưới. Sau đó, bạn có thể làm điều gì đó như:

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)] 

hoặc

zip(X.ravel(order='F'),Y.ravel(order='F')) 
# [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1)] 
+0

nó sẽ là tốt để cũng đề cập đến 'numpy.mgrid' và' numpy.ogrid' ở đây. –

1

NumPy của ndindex() công trình cho ví dụ bạn đưa ra, nhưng nó không phục vụ cho tất cả các trường hợp sử dụng. Không giống như của Python được xây dựng trong range(), cho phép cả một tùy ý start, stopstep, của numpy np.ndindex() chỉ chấp nhận một stop. (Các start được coi là (0,0,...), và step(1,1,...).)

Dưới đây là một thực hiện đóng vai trò giống như được xây dựng trong range() chức năng. Tức là, nó cho phép các đối số start/stop/step tùy ý, nhưng nó hoạt động trên tuples thay vì chỉ các số nguyên.

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 

Ví dụ:

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

Chỉ trong thời gian cho chạy nước rút! – MaiaVictor

Các vấn đề liên quan