Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create array from two arrays elements in pairs without loops [duplicate]

Simple question here. I have arrays:

a = [ 600 746 8556 90456 ]
b = [ 684 864 8600 90500 ]

and I want to get:

output = [ a(1):b(1) a(2):b(2) a(3):b(3) a(4):b(4) ]

(or either [ a(1):b(1); a(2):b(2); a(3):b(3); a(4):b(4) ], I don't care)

I cannot realize how to do this without using a loop, but I know it should be a way.

Any idea?

thanks in advance

like image 682
myradio Avatar asked Dec 06 '22 22:12

myradio


1 Answers

Approach #1

Vectorized approach with bsxfun's masking capability -

%// Get "extents" formed with each pair of "a" and "b" and max extent
ext = b-a
max_ext = max(ext)

%// Extend all a's to max possible extent
allvals = bsxfun(@plus,a,[0:max_ext]')  %//'

%// Get mask of valid extensions and use it to have the final output
mask  = bsxfun(@le,[0:max_ext]',ext)  %//'
out  = allvals(mask).'

Approach #2

Listing here is a cumsum based approach that has to be more memory efficient and faster than both the earlier listed bsxfun based approach and arrayfun based approach in the other answer. Here's the code -

%// Get "extents" formed with each pair of "a" and "b"
ext = b-a;

%// Ignore cases when "a" might be greater than "b"
a = a(ext>=0);
b = b(ext>=0);
ext = b-a;

if numel(ext)>1

    %// Strategically place "differentiated" values from array,a
    idx = ones(sum(ext+1),1);
    idx([1 cumsum(ext(1:end-1)+1)+1]) = [a(1) diff(a)-ext(1:end-1)];

    %// Perform cumulative summation to have the final output
    out = cumsum(idx)

else %// Leftover cases when there are one or no valid boundaries:(a->b)
    out = a:b
end

Sample run -

>> a
a =
     6    12    43
>> b
b =
     8    17    43
>> out
out =
     6     7     8    12    13    14    15    16    17    43
like image 60
Divakar Avatar answered May 21 '23 22:05

Divakar