MATLAB中的数组块拆分

时间:2016-08-09 14:06:12

标签: arrays matlab

假设我们有一个包含零的的不同长度的矢量,例如:

0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0

我想将其转换为2D数组,如下所示。每行仅包含零和其中一个块。即2D数组的行数将是最后的块数。上面的数组将转换为:

0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0

即第一个块在第一行结束,第二个块在第二行结束等。

问题

这个练习使用循环相当简单。我的问题是,如果有一种利用MATLAB矩阵运算,MATLAB函数和数组索引的简洁方法来做到这一点吗?

2 个答案:

答案 0 :(得分:2)

在我的头顶,您可以使用bwlabel(来自图像处理工具箱)为1的每个群集分配一个唯一值。然后,您可以使用bsxfun检查标记版本与唯一标签之间的相等性,这将自动将其展开为矩阵。

a = [0 0 0 1 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 0 0 1 1 1 0 0 0];
b = bwlabel(a);
out = bsxfun(@eq, (1:max(b))', b);

如果没有图像处理工具箱,您可以通过以下方式有效地完成同样的事情:

C = cumsum(~a);
out = bsxfun(@eq, unique(C(logical(a))).', C);

答案 1 :(得分:1)

我试过这个

N = 100;              % set array size
A = randi(2,N,1)-1;   % generate random array filled with 0 and 1

d = diff([0;A]);      % if  1 : starting point of block
                      % if -1 : end      point of block
ir = find(A);         % Find A==1 which will be row index
ic = cumsum(d(ir)>0); % Set col index

% assemble array
    % if you want output as full array
    A_new = accumarray([ir,ic],ones(size(ir)),[length(A),ic(end)]); 

    % if you want output as sparse array
    A_new = sparse(ir,ic,ones(size(ir)),length(A),ic(end),length(ir));

% display routine
figure;spy(A,'r');hold on;spy([zeros(size(A)),A_new]);

事实证明它比@Suever的解决方案更快(比较tic toc时间与10000,1000试验)。此外,如果您使用sparse代替accumarray,那么它会更快

Suever_time = 7~8 sec
Accumarray  = 2~3 sec
Sparse      = 0.2~0.3 sec

然而,他的那个更短更整洁!