1
votes

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

2
How can it be a 2D numeric matrix, it doesn't have equal number of elements in each row. Or are you looking for a cell array?Divakar
Good point. (Having trouble transitioning to vector-wise programming. Padded with zeros to match the largest row?La bla bla
Yeah padding could be done. So, padding at the end?Divakar
Also, is Z always sorted?Divakar
Yes, always sorted and always starts at 1 and ends with 255La bla bla

2 Answers

2
votes

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
2
votes

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:

enter image description hereenter image description here

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?)