Reputation: 8708
Say I have the following columns vector Z
1 53 55 57 60 64 68 70 71 72 74 76 77 78 79 80 255
I want to use it to create a matrix such that each row would contain all the number between (and including) 2 adjacent elements in Z
So the output matrix should be something like this:
1 2 3 .... 53
53 54 55
55 56 57
57 58 60
....
80 81 ... 255
I've been searching for something similar but couldn't find it.
Thanks
Upvotes: 1
Views: 205
Reputation: 1641
Try this to break the monotony of bsxfun
:) :
d = diff(Z);
N = max(d)+1;
R = zeros(length(Z)-1,N);
for i = 1:length(Z)-1
R(i,1:1+d(i)) = Z(i):Z(i+1);
end
EDIT:
I know that the general consensus is that one always should try to avoid loops in Matlab, but is this valid for this example? I know that this is a broad question, so lets focus on this particular problem and compare bsxfun
to JIT loop. Comparing the two proposed solutions:
the code used for testing:
Z = [1 53 55 57 60 64 68 70 71 72 74 76 77 78 79 80 255];
%[1 3 4, 6];
nn = round(logspace(1,4,10));
tm1_nn = zeros(length(nn),1);
tm2_nn = zeros(length(nn),1);
for o = 1:length(nn)
tm1 = zeros(nn(o),1);
tm2 = zeros(nn(o),1);
% approach1
for k = 1:nn(o)+1
tic
d = diff(Z);
N = max(d)+1;
R = zeros(length(Z)-1,N);
for i = 1:length(Z)-1
R(i,1:1+d(i)) = Z(i):Z(i+1);
end
tm1(k) = toc;
end
%approach 2
for k = 1:nn(o)+1
tic
lens = diff(Z)+1;
mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.';
tm2(k) = toc;
end
tm1_nn(o) = mean(tm1);%sum(tm1);%mean(tm1);%
tm2_nn(o) = mean(tm2);%sum(tm2);%mean(tm2);%
end
semilogx(nn,tm1_nn, '-ro', nn,tm2_nn, '-bo')
legend('JIT loop', 'bsxfun')
xlabel('log_1_0(Number of runs)')
%ylabel('Sum execution time')
ylabel('Mean execution time')
grid on
I encountered other tasks previously where the loop was faster. (or I mess up the comparison?)
Upvotes: 2
Reputation: 221574
See if this works for you -
lens = diff(Z)+1;
mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.'; %//'# out is the desired output
Upvotes: 2