Clear Filters
Clear Filters

Value assignment to vector, without loop

19 views (last 30 days)
ckara
ckara on 13 May 2020
Commented: Tommy on 14 May 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

Accepted Answer

Tommy
Tommy on 13 May 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 Comments
ckara
ckara on 13 May 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 on 14 May 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!

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!