This question already has an answer here:
My question is similar to this one, but I would like to replicate each element according to a count specified in a second array of the same size.
An example of this, say I had an array v = [3 1 9 4]
, I want to use rep = [2 3 1 5]
to replicate the first element 2 times, the second three times, and so on to get [3 3 1 1 1 9 4 4 4 4 4]
.
So far I'm using a simple loop to get the job done. This is what I started with:
vv = [];
for i=1:numel(v)
vv = [vv repmat(v(i),1,rep(i))];
end
I managed to improve by preallocating space:
vv = zeros(1,sum(rep));
c = cumsum([1 rep]);
for i=1:numel(v)
vv(c(i):c(i)+rep(i)-1) = repmat(v(i),1,rep(i));
end
However I still feel there has to be a more clever way to do this... Thanks
accumarray
function can be used to make the code work if zeros exit inrep
arrayThis works similar to solution of gnovice, except that indices are accumulated instead being assigned to 1. This allows to skip some indices (3 and 6 in the example below) and remove corresponding elements from the output.
What you are trying to do is to run-length decode. A high level reliable/vectorized utility is the FEX submission
rude()
:the result
Note that this function performs the opposite operation as well, i.e. run-length encodes a vector or in other words returns
values
and the correspondingcounts
.Here's one way I like to accomplish this:
This works by first creating an index vector of zeroes the same length as the final count of all the values. By performing a cumulative sum of the
rep
vector with the last element removed and a 1 placed at the start, I get a vector of indices intoindex
showing where the groups of replicated values will begin. These points are marked with ones. When a cumulative sum is performed onindex
, I get a final index vector that I can use to index intov
to create the vector of heterogeneously-replicated values.To add to the list of possible solutions, consider this one:
This is much slower than the one by gnovice..