2009-02-03 87 views
8

Tôi có một vấn đề Java nhỏ mà tôi muốn dịch sang Python. Tôi cần một mảng đa chiều. Trong Java, có vẻ như:Mảng đa chiều trong Python

double dArray[][][] = new double[x.length()+1][y.length()+1][x.length()+y.length()+3]; 
dArray[0][0][0] = 0; 
dArray[0][0][1] = POSITIVE_INFINITY; 

Giá trị tiếp theo sẽ được tạo thành vòng lặp và được ghi vào mảng.

Làm cách nào để tạo nhanh mảng?

PS: Không có phép nhân ma trận tham gia ...

+0

Ngẫu nhiên, bạn có thể nhận được dấu chấm động vô cực trong python như' float ('inf') '. Nó hoạt động nhiều hơn hoặc ít hơn như bạn mong đợi - hầu hết các hoạt động chỉ cung cấp cho bạn inf, và một vài cung cấp cho bạn nan. –

+0

(được kết hợp với câu hỏi trước đó, giữ nguyên bản gốc như sau: OP vẫn tồn tại, b: câu hỏi có độ phân giải cao hơn và c: để tránh nhiều necromancer) –

Trả lời

11

Bạn có thể tạo ra nó sử dụng danh sách lồng nhau:

matrix = [[a,b],[c,d],[e,f]] 

Nếu nó có phải năng động đó là phức tạp hơn, tại sao không viết một lớp học nhỏ cho mình?

class Matrix(object): 
    def __init__(self, rows, columns, default=0): 
     self.m = [] 
     for i in range(rows): 
      self.m.append([default for j in range(columns)]) 

    def __getitem__(self, index): 
     return self.m[index] 

Điều này có thể được sử dụng như thế này:

m = Matrix(10,5) 
m[3][6] = 7 
print m[3][6] // -> 7 

tôi chắc chắn rằng người ta có thể thực hiện nó hiệu quả hơn. :)

Nếu bạn cần mảng đa chiều, bạn có thể tạo mảng và tính toán độ lệch hoặc bạn sử dụng mảng trong mảng trong mảng, điều này có thể khá tệ đối với bộ nhớ.(Có thể là nhanh hơn mặc dù ...) Tôi đã thực hiện những ý tưởng đầu tiên như thế này:

class Matrix(object): 
    def __init__(self, *dims): 
     self._shortcuts = [i for i in self._create_shortcuts(dims)] 
     self._li = [None] * (self._shortcuts.pop()) 
     self._shortcuts.reverse() 

    def _create_shortcuts(self, dims): 
     dimList = list(dims) 
     dimList.reverse() 
     number = 1 
     yield 1 
     for i in dimList: 
      number *= i 
      yield number 

    def _flat_index(self, index): 
     if len(index) != len(self._shortcuts): 
      raise TypeError() 

     flatIndex = 0 
     for i, num in enumerate(index): 
      flatIndex += num * self._shortcuts[i] 
     return flatIndex 

    def __getitem__(self, index): 
     return self._li[self._flat_index(index)] 

    def __setitem__(self, index, value): 
     self._li[self._flat_index(index)] = value 

có thể được sử dụng như thế này:

m = Matrix(4,5,2,6) 
m[2,3,1,3] = 'x' 
m[2,3,1,3] // -> 'x' 
3

Đối với dữ liệu số, Numpy Arrays:

>>> matrix1 = array(([0,1],[1,3])) 
>>> print matrix1 
[[0 1] 
[1 3]] 

Đối với dữ liệu chung (ví dụ dây), bạn có thể sử dụng một danh sách liệt kê, danh sách các tuples, ...

matrix2 = [['a','b'], ['x','y']] 
+0

Tôi có thể khởi tạo cho nó một số lượng nhất định các hàng và cột như trong C? –

+0

Các đối tượng có thể thay đổi (ví dụ: danh sách) có thể thay đổi - vì vậy việc khởi tạo không phải lúc nào cũng có liên quan. Trong numpy, một mảng có một hình dạng (kích thước) có thể được sửa đổi mà không thay đổi dữ liệu. – gimel

+1

@Popper: Có. số không ((3,4)) sẽ tạo ra một dãy số không 3x4. –

18

Nếu bạn giới hạn mình vào các thư viện chuẩn của Python, sau đó một danh sách liệt kê là xây dựng gần nhất:

arr = [[1,2],[3,4]] 

cho mảng 2d. Các hàng có thể được truy cập dưới dạng arr[i] cho i trong {0,..,len(arr}, nhưng việc truy cập cột là khó khăn.

Nếu bạn sẵn sàng thêm phụ thuộc vào thư viện, gói NumPy là những gì bạn thực sự muốn. Bạn có thể tạo một mảng cố định chiều dài từ một danh sách liệt kê sử dụng:

import numpy 
arr = numpy.array([[1,2],[3,4]]) 

truy cập Cột là giống như đối với danh sách danh sách-of-, nhưng truy cập cột là dễ dàng: arr[:,i] cho i trong {0,..,arr.shape[1]} (số cột).

Trong thực tế, các mảng NumPy có thể là n-chiều.

mảng rỗng có thể được tạo ra với

numpy.empty(shape) 

nơi shape là một tuple của kích thước trong mỗi chiều; shape=(1,3,2) cung cấp mảng 3-d với kích thước 1 trong thứ nguyên đầu tiên, kích thước 3 trong thứ nguyên thứ hai và 2 trong thứ nguyên thứ 3.

Nếu bạn muốn lưu trữ các đối tượng trong một mảng NumPy, bạn có thể làm điều đó cũng như:

arr = numpy.empty((1,), dtype=numpy.object) 
arr[0] = 'abc' 

Để biết thêm về các dự án NumPy, hãy kiểm tra NumPy homepage.

+0

Không cần sử dụng tuple. 'numpy.empty ([1])' cũng hoạt động. – jfs

+0

Trình tạo số ngẫu nhiên đơn giản: 'noise = lambda: numpy.empty ([1]) [0]' – jfs

+0

Đúng, bất kỳ phép lặp nào (danh sách, bộ, vv) hoạt động như đối số thứ nguyên. Trình tạo số "ngẫu nhiên" của bạn dựa vào bộ nhớ chưa được khởi tạo là "ngẫu nhiên" và nên * không bao giờ * được sử dụng như một nguồn ngẫu nhiên cho bất kỳ thứ gì có độ chín (ví dụ: mật mã). –

13

Để tạo một mảng python tiêu chuẩn của mảng kích thước tùy ý:

a = [[0]*cols for _ in [0]*rows] 

Nó được truy cập như thế này:

a[0][1] = 5 # set cell at row 0, col 1 to 5 

Một Gotcha trăn nhỏ đó là đáng nói: Nó được cám dỗ để chỉ cần gõ

a = [[0]*cols]*rows 

nhưng điều đó sẽ sao chép các cùng mảng cột cho mỗi hàng, dẫn đến hành vi không mong muốn. Cụ thể:

>>> a[0][0] = 5 
>>> print a[1][0] 
5 
+4

Tôi muốn sử dụng: '[[0] * cols cho _ trong xrange (hàng)]' – jfs

+0

@ J.F.Sebastian Ya tôi quá, thực sự. Tôi chỉ tìm thấy sự đối xứng hấp dẫn tại thời điểm viết bài này. :-) – Deestan

+0

plus1 cho hình ảnh xác thực. – AShelly

10

Mảng đa chiều có chút ít âm u. Có rất ít lý do để sử dụng chúng và nhiều lý do để suy nghĩ hai lần và sử dụng một cái gì đó khác phản ánh đúng hơn những gì bạn đang làm. [Dấu. câu hỏi của bạn rất mỏng về ngữ cảnh ;-)]

Nếu bạn đang thực hiện phép toán ma trận, hãy sử dụng numpy.

Tuy nhiên, một số người đã làm việc với các ngôn ngữ buộc họ sử dụng mảng đa chiều vì đó là tất cả những gì họ có. Nếu bạn già như tôi (tôi bắt đầu lập trình vào những năm 70) thì bạn có thể nhớ những ngày mà mảng đa chiều là cấu trúc dữ liệu duy nhất bạn có. Hoặc, kinh nghiệm của bạn có thể giới hạn bạn với các ngôn ngữ mà bạn phải biến vấn đề của mình thành mảng đa chiều.

Giả sử bạn có một bộ sưu tập n Điểm 3D. Mỗi điểm có giá trị x, y, z và thời gian. Đây có phải là một mảng n x 4 không? Hoặc mảng 4 * n? Không hẳn.

Vì mỗi điểm có 4 giá trị cố định, đây là danh sách các bộ dữ liệu đúng hơn.

a = [ (x, y, z, t), (x, y, z, t), ... ] 

Vẫn còn tốt hơn, chúng tôi có thể thể hiện điều này như một danh sách các đối tượng.

class Point(object): 
    def __init__(self, x, y, z, t): 
     self.x, self.y, self.z, self.t = x, y, z, t 

a = [ Point(x,y,x,t), Point(x,y,z,t), ... ] 
+1

+1. Tôi muốn đề cập đến 'namedtuple's – jfs

0

Một lựa chọn khác là sử dụng một từ điển:

>>> from collections import defaultdict 
>>> array = defaultdict(int) # replace int with the default-factory you want 
>>> array[(0,0)] 
0 
>>> array[(99,99)] 
0 

Bạn sẽ cần phải theo dõi các thượng & cận dưới là tốt.

11

Hãy xem numpy

Dưới đây là một đoạn mã cho bạn

import numpy as npy 

d = npy.zeros((len(x)+1, len(y)+1, len(x)+len(y)+3)) 
d[0][0][0] = 0 # although this is unnecessary since zeros initialises to zero 
d[i][j][k] = npy.inf 

Tôi không nghĩ bạn cần triển khai ứng dụng khoa học biện minh cho việc sử dụng numpy. Nó nhanh hơn và linh hoạt hơn và bạn có thể lưu trữ khá nhiều thứ. Vì tôi nghĩ rằng có lẽ tốt hơn nên thử và biện minh cho không sử dụng số. Có những lý do chính đáng, nhưng nó có thêm rất nhiều chi phí và rất ít nên nó xứng đáng được xem xét.

P.S. Độ dài mảng của bạn có đúng không? Nó trông giống như một ma trận hình khá đặc biệt ...

4

Có lẽ không phù hợp cho bạn, nhưng nếu bạn đang làm việc ma trận nghiêm túc thấy numpy

5

Nếu bạn là OK sử dụng mảng thưa thớt, bạn có thể sử dụng một dict để lưu trữ của bạn giá trị. dicts Python cho phép bạn sử dụng các bộ như phím, như vậy, bạn có thể gán cho và truy cập các yếu tố của "mảng thưa thớt" (mà thực sự là một dict đây) như thế này:

d = {} 
d[0,2,7] = 123 # assign 123 to x=0, y=2, z=7 
v = d[0,2,7] 
+0

Bí quyết tốt để lưu trữ mảng đa chiều. Tuy nhiên mọi thứ sẽ trở nên rất lộn xộn khi cố gắng lặp qua các phần tử nói về một cột hoặc một hàng hoặc thậm chí để có thể nhận được 'thứ nguyên'. –

+0

Thật vậy. Nếu tôi đã sử dụng một cái gì đó như thế này, tôi tất nhiên sẽ đóng gói này vào một lớp học và giới thiệu các phương pháp để đọc/ghi truy cập. Một biến cá thể sẽ lưu trữ thứ nguyên của mảng và các phương thức đọc/ghi sẽ trả về giá trị mặc định cho các phần tử chưa được gán (bằng cách bắt KeyError). – paprika

+0

+1: từ điển đơn giản hơn nhiều. Lặp lại kích thước rất dễ dàng, không lộn xộn. xRange = set ([k [0] cho k trong d.keys()]), yRange = set ([k [1] cho k trong d.keys()]) –

2

Dưới đây là một cách nhanh chóng để tạo ra một lồng danh sách 3 chiều khởi tạo với số không:

# dim1, dim2, dim3 are the dimensions of the array 
a =[[[0 for _ in range(dim1)] for _ in range(dim2)] for _ in range(dim1) ] 
a[0][0][0] = 1 

đây là một danh sách liệt kê các danh sách, một chút linh hoạt hơn một mảng, bạn có thể làm:

a[0][0] = [1,2,3,4] 

để thay thế toàn bộ liên tiếp trong mảng, hoặc ev vi lạm dụng nó như thế:

a[0] = "Ouch" 
print a[0][0] #will print "O", since strings are indexable the same way as lists 
print a[0][0][0] #will raise an error, since "O" isn't indexable 

nhưng nếu bạn cần hiệu suất, thì tôi đồng ý rằng đó là cách để đi.

Ngoài ra, hãy cẩn thận của:

a = [[[0] * 5]*5]*5] 

Nếu bạn cố gắng a[0][0][0]=7 trên đối tượng trên, bạn sẽ thấy có gì sai với điều đó.

0

Tôi vừa bước vào một nhu cầu tương tự và mã hóa này:

def nDimensionsMatrix(dims, elem_count, ptr=[]): 
    if (dims > 1): 
     for i in range(elem_count[dims-1]): 
      empty = [] 
      ptr.append(empty) 
      nDimensionsMatrix(dims-1, elem_count, empty) 
     return ptr 
    elif dims == 1: 
     ptr.extend([0 for i in range(elem_count[dims])]) 
     return ptr 

matrix = nDimensionsMatrix(3, (2,2,2)) 

Tôi không nhìn vào tốc độ, chỉ funcionality;)

Tôi muốn tạo ra một ma trận với kích thước N và khởi tạo với 0 (a elem_count số phần tử trong mỗi thứ nguyên).

Hy vọng giúp mình một ai đó

0

dễ dàng, khi sử dụng NumPy:

b = ones((2,3,4)) # creates a 2x3x4 array containing all ones. 

'người' có thể được thay thế bằng 'số không'