假设我们有一个包含零的块的不同长度的矢量,例如:
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函数和数组索引的简洁方法来做到这一点吗?
答案 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
然而,他的那个更短更整洁!