列表列表的子矩阵(没有numpy)

the*_*olf 10 python matrix python-3.x

假设我有一个由列表列表组成的矩阵,如下所示:

>>> 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]]
Run Code Online (Sandbox Code Playgroud)

还假设我有一个相同结构的numpy矩阵,称为LoLa:

>>> LoLa=np.array(LoL)
Run Code Online (Sandbox Code Playgroud)

使用numpy,我可以得到这个矩阵的子矩阵,如下所示:

>>> LoLa[1:4,2:5]
array([[2, 3, 4],
       [2, 3, 4],
       [2, 3, 4]])
Run Code Online (Sandbox Code Playgroud)

我可以在纯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]] 
Run Code Online (Sandbox Code Playgroud)

这不是世界上最简单的东西,也不是最有效的:-)

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

unu*_*tbu 13

In [74]: [row[2:5] for row in LoL[1:4]]
Out[74]: [[2, 3, 4], [2, 3, 4], [2, 3, 4]]
Run Code Online (Sandbox Code Playgroud)

您还可以通过定义以下子类来模仿NumPy的语法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])
Run Code Online (Sandbox Code Playgroud)

也是收益率

[[2, 3, 4], [2, 3, 4], [2, 3, 4]]
Run Code Online (Sandbox Code Playgroud)

使用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
Run Code Online (Sandbox Code Playgroud)

但速度并非一切 - 有时可读性更重要.


Ray*_*Ray 5

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

r = slice(1,4)
s = slice(2,5)
[LoL[i][s] for i in range(len(LoL))[r]]
Run Code Online (Sandbox Code Playgroud)

如果您只是直接遍历列表列表,您可以将其写为:

[row[s] for row in LoL[r]]
Run Code Online (Sandbox Code Playgroud)