Matlab: Convert elements larger (smaller) than 1 (-1) into a sequence of 1 (-1)
matlab, vector, vectorization
Solution
You can use the good old cumsum-approach to repeating the entries properly. Note that I'm assigning a few temporary variables that you can get rid of, if you want to put everything into one line.
%# create a list of values to repeat
signVec = sign(Vec);
%# create a list of corresponding indices that repeat
%# as often as the value in signVec has to be repeated
tmp = max(abs(Vec),1); %# max: zeros have to be repeated once
index = zeros(sum(tmp),1);
index([1;cumsum(tmp(1:end-1))+1])=1; %# assign ones a pivots for cumsum
index = cumsum(index); %# create repeating indices
%# repeat
out = signVec(index);
out'
out =
0 1 1 1 -1 -1 -1 -1 0 0 1 1 1 -1
Problem
UPDATE: I've done some testing, and the solution of Jonas is the fastest for a range of different size input vectors. In particular, as angainor points out, the solution scales up to large sizes incredibly well - an important test as it is usually the large size problems that prompt us to pose these kind of questions on SO. Thanks to both Jonas and tmpearce for your solutions - based on the efficiency of the solution for large size problems I'm giving the answer tick to Jonas. My Question: I have this column vector: ``` Vec = [0; 1; 2; -1; -3; 0; 0; 2; 1; -1]; ``` I would like to convert every element greater than one into a sequence of ones that has length equal to the value of the element. Similarly, I want to convert every element less than minus one into a sequence of minus ones. Thus my output vector should look like this: ``` VecLong = [0; 1; 1; 1; -1; -1; -1; -1; 0; 0; 1; 1; 1; -1]; ``` Note that each 2 has been changed into two 1's, while the -3 has been changed into three -1's. Currently, I solve the problem like this: ``` VecTemp = Vec; VecTemp(VecTemp == 0) = 1; VecLong = NaN(sum(abs(VecTemp)), 1); c = 1; for n = 1:length(Vec) if abs(Vec(n)) <= 1 VecLong(c) = Vec(n); c = c + 1; else VecLong(c:c + abs(Vec(n))) = sign(Vec(n)); c = c + abs(Vec(n)); end end ``` This doesn't feel very elegant. Can anyone suggest a better method? Note: You can assume that `Vec` will contain only integer values. Thanks in advance for all suggestions.