How to generate a single vector of block-consecutive values from 2 vectors of same size without a loop ?
Mostrar comentarios más antiguos
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 comentario
Amro
el 20 de Jun. de 2014
here is a similar question on Stack Overflow: Vectorized array creation from a list of start/end indices
Respuesta aceptada
Más respuestas (6)
Andrei Bobrov
el 16 de Jun. de 2014
Editada: Andrei Bobrov
el 17 de Jun. de 2014
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
el 17 de Jun. de 2014
Editada: Sean de Wolski
el 17 de Jun. de 2014
2 votos
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.
1 comentario
jyloup p
el 17 de Jun. de 2014
Azzi Abdelmalek
el 16 de Jun. de 2014
Editada: Azzi Abdelmalek
el 16 de Jun. de 2014
cell2mat(arrayfun(@(x,y) x:y,a,b,'un',0))
1 comentario
Amro
el 20 de Jun. de 2014
slightly simplified: cell2mat(arrayfun(@colon,a,b,'un',0))
jyloup p
el 16 de Jun. de 2014
0 votos
jyloup p
el 17 de Jun. de 2014
2 comentarios
jyloup p
el 17 de Jun. de 2014
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.
Categorías
Más información sobre Calendar en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!