2013-03-27 29 views
9

Giả sử tôi có một ma trận bao gồm một danh sách liệt kê như sau:ma trận Sub của một danh sách liệt kê (không NumPy)

>>> LoL=[list(range(10)) for i in range(10)] 
>>> LoL 
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] 

Giả, cũng có thể, rằng tôi có một ma trận NumPy của cấu trúc tương tự được gọi là LoLa:

>>> LoLa=np.array(LoL) 

Sử dụng numPy, tôi có thể có được một submatrix của ma trận này như thế này:

>>> LoLa[1:4,2:5] 
array([[2, 3, 4], 
     [2, 3, 4], 
     [2, 3, 4]]) 

tôi có thể replic ăn miếng NumPy ma trận trong tinh khiết Python như vậy:

>>> r=(1,4) 
>>> s=(2,5) 
>>> [LoL[i][s[0]:s[1]] for i in range(len(LoL))][r[0]:r[1]] 
[[2, 3, 4], [2, 3, 4], [2, 3, 4]] 

nào không phải là điều đơn giản nhất trên thế giới để đọc cũng không phải :-) hiệu quả nhất

Câu hỏi: Có một cách dễ dàng hơn (trong tinh khiết Python) để cắt một ma trận tùy ý thành ma trận phụ?

Trả lời

11
In [74]: [row[2:5] for row in LoL[1:4]] 
Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]] 

Bạn có thể cú pháp cũng bắt chước NumPy của bằng cách định nghĩa một lớp con của list:

class LoL(list): 
    def __init__(self, *args): 
     list.__init__(self, *args) 
    def __getitem__(self, item): 
     try: 
      return list.__getitem__(self, item) 
     except TypeError: 
      rows, cols = item 
      return [row[cols] for row in self[rows]] 

lol = LoL([list(range(10)) for i in range(10)]) 
print(lol[1:4, 2:5]) 

cũng mang lại

[[2, 3, 4], [2, 3, 4], [2, 3, 4]] 

Sử dụng LoL lớp con sẽ không giành chiến thắng bất kỳ kiểm tra tốc độ :

In [85]: %timeit [row[2:5] for row in x[1:4]] 
1000000 loops, best of 3: 538 ns per loop 
In [82]: %timeit lol[1:4, 2:5] 
100000 loops, best of 3: 3.07 us per loop 

nhưng tốc độ không phải là mọi thứ - đôi khi khả năng đọc quan trọng hơn.

+0

Phần thứ hai * hoàn toàn * đánh cắp câu trả lời của tôi! :-)) +1 – dawg

+1

Chúc mừng, @drewk; tiếp theo là tất cả của bạn :) – unutbu

5

Thứ nhất, bạn có thể sử dụng slice đối tượng trực tiếp, giúp một chút với cả khả năng đọc và hiệu suất:

r = slice(1,4) 
s = slice(2,5) 
[LoL[i][s] for i in range(len(LoL))[r]] 

Và nếu bạn chỉ cần lặp qua các danh sách danh sách-of-trực tiếp, bạn có thể viết rằng như:

[row[s] for row in LoL[r]] 
0

tôi không biết nếu nó dễ dàng hơn, nhưng hãy để tôi ném một ý tưởng bảng:

from itertools import product 
r = (1+1, 4+1) 
s = (2+1, 5+1) 
array = [LoL[i][j] for i,j in product(range(*r), range(*s))] 

Đây là phiên bản phẳng của submatrix bạn muốn.

1

Làm điều này,

submat = [[mat [i] [j] cho j trong phạm vi (index1, index2)] for i in range (index3, index4)]

các submat sẽ hình chữ nhật (vuông nếu index3 == index1 và index2 == index4) đoạn của ma trận lớn ban đầu của bạn.

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