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
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With