根据范围索引从矩阵中提取行?

3

我有一个大小为NxM的矩阵A。我还有一个包含索引对的数组B,这些索引对表示我想要提取的A的行。

示例

A = [ 1  2  3 %1
      4  5  6 %2
      7  8  9 %3
     10 11 12 %4
     13 14 15 %5
     16 17 18]%6
B = [1 2
     4 6]

我希望C包含A的第1到2行和第4到6行。

C = [ 1  2  3 %1
      4  5  6 %2
     10 11 12 %4
     13 14 15 %5
     16 17 18]%6

有没有一种不需要迭代 B 的方法来实现这个?我尝试过C = A(B,:),但它没有起作用(我也不指望它会。。)。
2个回答

7

利用bsxfun的冒号模拟功能,它利用了一对bsxfun(@lebsxfun(@ge

N = size(A,1)
[R,~] = find((bsxfun(@le,B(:,1),1:N) & bsxfun(@ge,B(:,2),1:N)).')
out = A(R,:)

示例运行 #1 -

>> A
A =
     1     2     3
     4     5     6
     7     8     9
    10    11    12
    13    14    15
    16    17    18
>> B
B =
     1     2
     4     6
>> out
out =
     1     2     3
     4     5     6
    10    11    12
    13    14    15
    16    17    18

示例运行 #2(展示如何处理重叠) -


>> A
A =
     1     2     3
     4     5     6
     7     8     9
    10    11    12
    13    14    15
    16    17    18
>> B
B =
     1     2
     4     6
     3     5
>> out
out =
     1     2     3
     4     5     6
    10    11    12
    13    14    15
    16    17    18
     7     8     9
    10    11    12
    13    14    15

虽然不是矢量化的解决方案,但更节省内存的解决方案可能是使用冒号运算符 -

idx = arrayfun(@colon, B(:,1), B(:,2), 'Uni', 0)
out = A([idx{:}],:)

你可以使用 idx = cell2mat(arrayfun(@colon, B(:,1), B(:,2), 'Uni', 0).') 直接获取 idx - Mohsen Nosratinia
@MohsenNosratinia 是的,这是从单元数组中提取的另一种方法,谢谢! - Divakar

2

当然,愚蠢的方法是使用 for 循环:

C = []; % Initialise empty matrix
for ii = 1:size(B,1)
   Ctmp = A(B(ii,1):B(ii,2),:); % Extract rows
   C = [C;Ctmp]; % Add them to the existing matrix
end

或者使用 zeros(sum(diff(B,[],2)+1),size(A,2)) 进行初始化。但是索引可能会变得有点复杂。 - Divakar
这个方法比较占用内存,但是作为bsxfun的新手来说,这是我的一个快速而简单的解决方案。只要你的数组不是过分庞大,时间差别并不会太大。 - Adriaan

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