使用包含 2 个角的索引的向量提取子矩阵的最短命令 [matlab]

Shortest command to extract a submatrix using a vector containing the indexes of the 2 corners [matlab]

假设我们有以下矩阵

A=magic(4)

16     2     3    13
 5    11    10     8
 9     7     6    12
 4    14    15     1

我们要提取 3 个子矩阵,由左上角和右下角的索引标识。子矩阵的索引包含在矩阵的一行中 ii 的第 1 列和第 2 列是角的行索引,i 的第 3 列和第 4 列是角的列索引。

i =

 1     1     1     3
 2     4     1     2
 3     4     3     4

>> A(i(1,1):i(1,2),i(1,3):i(1,4))

ans =

16     2     3

>> A(i(2,1):i(2,2),i(2,3):i(2,4))

ans =

 5    11
 9     7
 4    14

>> A(i(3,1):i(3,2),i(3,3):i(3,4))

ans =

     6    12
    15     1

我用来提取子矩阵的命令A(i(,):i(,),i(,):i(,))不是很方便,所以我想知道有没有更好的方法来完成这项工作?

如果你不想全部输入,那为什么不写一个包装函数呢?

A = magic(4);
S = @(r) A(i(r,1):i(r,2),i(r,3):i(r,4));
S(1)
S(2)
S(3)

如果 A 在定义 S 之后可能会发生变化,那么您需要将其作为函数的参数。

S = @(A,r) A(i(r,1):i(r,2),i(r,3):i(r,4));
A = magic(4)
S(A,1)
S(A,2)
S(A,3)

同样,如果 i 可能会发生变化,那么您也需要将其设为参数。

编辑 不幸的是,与我的评论相反,如果你想执行赋值,那么 A(I(r)) 将不会像你发布的那样工作,因为这总是 returns 一个数组而不是一个矩阵。一种可能的解决方法是使用元胞数组代替 comma-separated-lists,但这不如只读选项优雅。例如

S = @(r) {i(r,1):i(r,2) , i(r,3):i(r,4)};
s = S(1); A(s{:})
s = S(2); A(s{:})
s = S(3); A(s{:})

遵循相同的原则,您可以 pre-define 来自 i 的元胞数组来访问一行。

s = arrayfun(@(r) {i(r,1):i(r,2),i(r,3):i(r,4)}, 1:size(i,1), 'UniformOutput', false);
A(s{1}{:})
A(s{2}{:})
A(s{3}{:})