一个列表中的子矩阵(不使用numpy)

12

假设我有一个由嵌套列表组成的矩阵,像这样:

>>> 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]]
假设我有一个结构相同的numpy矩阵,名为LoLa
>>> LoLa=np.array(LoL)
使用numpy,我可以像这样获取该矩阵的子矩阵:
>>> LoLa[1:4,2:5]
array([[2, 3, 4],
       [2, 3, 4],
       [2, 3, 4]])
我可以使用纯Python复制numpy矩阵的切片,如下所示:
>>> 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]] 

这不是世界上最容易阅读或最有效的事情 :-)

问题:是否有一种更简单的方法(在纯Python中)将任意矩阵切片为子矩阵?

4个回答

15
In [74]: [row[2:5] for row in LoL[1:4]]
Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
你也可以通过定义list的子类来模仿NumPy的语法:
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])

同样也产生

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

使用 LoL 子类不会赢得任何速度测试:

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

但速度并不是一切 -- 有时易读性更为重要。


第二部分完全抄袭了我的答案!:-)) +1 - dawg
1
谢谢,@drewk;下一个就轮到你了 :) - unutbu

5

首先,您可以直接使用slice对象,这有助于提高可读性和性能:

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

如果你想直接遍历列表中的嵌套列表,你可以这样写:

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

1

执行以下操作:

submat = [ [ mat[ i ][ j ] for j in range( index1, index2 ) ] for i in range( index3, index4 ) ]

submat 将会是您原始大矩阵中的矩形块(如果index3 == index1 和 index2 == index4,则为正方形块)。


0

我不知道是否更容易,但让我向大家提出一个想法:

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

这是您所需子矩阵的扁平化版本。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接