Azzera filtri
Azzera filtri

Value assignment to vector, without loop

19 visualizzazioni (ultimi 30 giorni)
ckara
ckara il 13 Mag 2020
Commentato: Tommy il 14 Mag 2020
Any possible ways (-fastest preferably) of doing the following without a for loop:
out = zeros(20,1)
value = [1 2 3 4]
frm = [4 9 14 16]
to = [4 12 14 17]
for i=1:length(frm)
out(frm(i):to(i)) = value(i)
end

Risposta accettata

Tommy
Tommy il 13 Mag 2020
Here's an option:
N = 20;
idx = (1:N)';
out = (idx >= frm & idx <= to)*value';
The indices in frm and to can't overlap, and out will have 0s wherever the values in value aren't placed.
Here's a similar method which doesn't use matrix multiplication:
N = 20;
out = zeros(N,1);
idx = (1:N)';
tf = idx >= frm & idx <= to;
out(any(tf,2)) = repelem(value, sum(tf));
No idea how these compare to other methods - including a for loop.
  2 Commenti
ckara
ckara il 13 Mag 2020
Such an elegant solution. Thanks!
Your solution is way better than using arrayfun(), but out of pure curiosity, is there any solution using arrayfun, like: arrayfun(@(x) out(from:to)=value, x) ?
Tommy
Tommy il 14 Mag 2020
Happy to help!
The way you've written it, I don't believe so, no. When you use arrayfun, assignment to your variable happens outside the call to arrayfun, e.g.
out = arrayfun(@(i) value(i), 1:numel(value))
% ^ equal sign is here
arrayfun can't selectively place values, then. It could work if the function you supply to arrayfun returns every value in out, including the 0s. Then you've got to create a function that will return an element of value where appropriate and a 0 elsewhere, which would require checking if the input index falls within any elements in frm and to.
Or, your arrayfun function could return just the non-zero values as well as the indices required to fill out, and then you could fill out in the next line of code. Or there's this monstrosity that I came up with, which returns []s in place of 0s (requiring the use of a cell array), then replaces the []s with 0s, and then converts to a matrix:
N = 20;
out = arrayfun(@(i) value(i>=frm&i<=to), 1:N, 'uni', 0);
out(cellfun(@isempty, out)) = {0};
out = cell2mat(out)';
There are loads of ways you could do it, but I doubt any of them beat the for loop you wrote above. Of course I may be overlooking something!

Accedi per commentare.

Più risposte (0)

Categorie

Scopri di più su Loops and Conditional Statements in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by