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 で Calendar についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!