How to generate a single vector of block-consecutive values from 2 vectors of same size without a loop ?
이전 댓글 표시
Hello, I have 2 vectors of same size let's say a = [3 7 19 22] and b = [5 10 20 24]
And from those 2 vectors I want to generate without a loop a single vector:
v = [a(1):b(1) a(2):b(2) ... a(end):b(end)].
so here v=[3 4 5 7 8 9 10 19 20 22 23 24].
I found linspaceNDim(a,b,N) on File Exchange Linearly spaced multidimensional matrix without loop but it doesn't work here as I dont want a fixed number of values between a(i) and b(i), but only block-consecutive values : a(i):b(i). So here N is changing at each index i.
I tried a:.b but this syntax doesn't work on Matlab.
Thanks for you help.
댓글 수: 1
Amro
2014년 6월 20일
here is a similar question on Stack Overflow: Vectorized array creation from a list of start/end indices
채택된 답변
추가 답변 (6개)
Andrei Bobrov
2014년 6월 16일
편집: Andrei Bobrov
2014년 6월 17일
v = a(1):b(end);
v = v(any(bsxfun(@ge,v,a.')&bsxfun(@le,v,b.')));
other variant
zo = zeros(b(end) - a(1) + 2,1);
zo(a - a(1) + 1) = 1;
zo(b - a(1) + 2) = -1;
t = cumsum(zo(1:end-1)) > 0;
out = a(1):b(end);
v = out(t);
Sean de Wolski
2014년 6월 17일
편집: Sean de Wolski
2014년 6월 17일
2 개 추천
There's also FEX:mcolon which does exactly what you're looking for and has a mex implementation that may very well be the fastest.
Azzi Abdelmalek
2014년 6월 16일
편집: Azzi Abdelmalek
2014년 6월 16일
cell2mat(arrayfun(@(x,y) x:y,a,b,'un',0))
댓글 수: 1
Amro
2014년 6월 20일
slightly simplified: cell2mat(arrayfun(@colon,a,b,'un',0))
jyloup p
2014년 6월 17일
댓글 수: 2
jyloup p
2014년 6월 17일
That's not a fair comparison. If you generate your limits like that, with common intervals, then the for loop produces garbage. Also the pre-allocation becomes meaningless and the output keeps changing size, leading to poor performance.
If the data is set with non-overlapping intervals, like in the original question, then the loop is still faster:
vals = reshape(sort(randperm(10^6,1000)),2,[]);
a = vals(1,:);
b = vals(2,:);
tic
offset = b - a;
numVal = sum(offset + 1);
pos = 1;
your_data = ones(numVal,1);
for ii = 1:numel(offset)
your_data(pos:pos+offset(ii)) = a(ii):b(ii);
pos = pos + offset(ii) + 1;
end
toc
tic
zo = zeros(b(end) - a(1) + 2,1);
zo(a - a(1) + 1) = 1;
zo(b - a(1) + 2) = -1;
t = cumsum(zo(1:end-1)) > 0;
out = a(1):b(end);
v = out(t);
toc
Elapsed time is 0.003596 seconds.
Elapsed time is 0.024514 seconds.
That being said, I am always impressed by Andrei's tricks.
카테고리
도움말 센터 및 File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!