问题
In Matlab I have an array "latencies"
(size 1x11) and a cell array "Latencies_ms"
(size 1x298). latencies
is a smaller part of Latencies_ms
, i.e. the values in latencies
exist within Latencies_ms
. I want to be able to find each value in latencies
inside Latencies_ms
and then add 1000
to that value and repeat this 8 times inside Latencies_ms
.
So for example,
latencies = [62626 176578 284690 397708 503278 614724 722466]
and (a small sample of Latencies_ms)
Latencies_ms = {3458, 62626, 123456, 7891011, 121341, 222112, 176578}
I want the output to be
out = {3458, 62626, 63626, 64626, 65626, 66626, 67626, 68626, 69626, 70626, 123456, 7891011, 121341, 222112, 176578, 177578, 178578, 179578, 180578, 181578, 182578, 183578, 184578,}
As a starting point I decided to see if I could just replicate each element without adding 1000 and I have used the following code with repmat
:
out = arrayfun( @(x,b)[x; repmat({latencies},8,1)],...
Latencies_ms, ismember(cell2mat(Latencies_ms),latencies), 'uni', 0 );
out = vertcat(out4{:});
where I match the elements of latencies with Latencies_ms and then use repmat
however using it like this inserts the entire latencies
array at the correct locations rather than repeating the elements.
Then if I try using a for-loop like this:
for i=1:length(latencies)
out = arrayfun( @(x,b)[x; repmat({latencies(i)},8,1)],...
Latencies_ms, ismember(cell2mat(Latencies_ms),latencies), 'uni', 0 );
out = vertcat(out4{:});
end
it repeats just the last element of latencies so its correctly doing the replication but not of the correct elements.
I'm not too proficient with arrayfun
and I think its whole point is to avoid using for-loops so I'm sure this isn't the correct way anyway but I feel like I'm almost there... Does anyone know what I am missing???
I don't have to use arrayfun, I tried to do this using for-loops but it got a bit messy but there isn't a restriction on using just arrayfun I just want to get to the correct output!
回答1:
Here is a loopless way:
ind = ismember([Latencies_ms{:}] , latencies); %Indices of the values to be repeated
repvals = bsxfun(@plus, repmat([Latencies_ms{ind}], 9, 1).', 0:1000:8000); %Rep+increment
out = Latencies_ms;
out(ind) = mat2cell(repvals, ones(1, sum(ind)), 9); %Replacing with repeated+inc elements
out = [out{:}]; %Converting to comma-separated list and then concatenating horizontally
The factor 9
in 2nd and 4th line is there since the matched element is to be kept once and repeated 8 times with increments (total = 9 times). The second line can be written with implicit expansion in ≥ R2016b as:
repvals = repmat([Latencies_ms{ind}], 9, 1).' + (0:1000:8000);
arrayfun
is a one-line wrapper for a loop. It is still a loop. But loops have been significantly improved in newer versions (starting from R2015b) and sometimes their performance even surpass the vectorised code. So no need to avoid an easy loop that you can understand for complicated vectorisation unless it's a bottle-neck.
来源:https://stackoverflow.com/questions/51009288/replicate-elements-from-an-array-into-a-different-array-in-matlab