create y using x, without loop

6 vues (au cours des 30 derniers jours)
Jebidiah Light
Jebidiah Light le 8 Mai 2019
size x = 2,3
size y = 1,157
y(3:52,1) = 1; y(53:102) = 2;... I need this but in one line of code that doesn't involve a loop.
X is dynamically growing because it is pulling data from another array. In X, columns 1&2 represent the index of rows needed for Y; however, column 3 is data inputted to Y for each of those rows respectively. Columns 1&2 will always be ordered consecutively column 3 will not.
x =
[ 3 52 1
53 102 2
103 157 98]
y =
[0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 98 98 98...]
  3 commentaires
Jebidiah Light
Jebidiah Light le 8 Mai 2019
input 1's from column 3 to 52 then 2's from column 53 to 102 using x as index and data for y, which is 1,102.
Adam Danz
Adam Danz le 8 Mai 2019
Modifié(e) : Adam Danz le 8 Mai 2019
Your update helped with problem #2 (now we understand y is a row vector). Problem #1 still needs addressed though I think I have a guess...

Connectez-vous pour commenter.

Réponse acceptée

Adam Danz
Adam Danz le 8 Mai 2019
Modifié(e) : Adam Danz le 9 Mai 2019
No loop method (assuming consecutiveness)
This solution assumes the indices defined in columns 1&2 are consecutive and without gaps.
y = [zeros(1,x(1,1)-1), repelem(x(:,3),x(:,2)-x(:,1)+1,1)'];
No loop method (the silly method)
This method works even when indices are not consecutive and have gaps.
x = [ 3 52 1
53 102 2];
xc = mat2cell(x,ones(1,size(x,1)),size(x,2));
yc = cellfun(@(x)ones(1,x(2)-x(1)+1).*x(3), xc, 'UniformOutput',false);
xIdx = cellfun(@(x)x(1):x(2), xc,'UniformOutput', false);
y = zeros(1,max(max(x(:,[1,2]))));
y(cell2mat(xIdx')) = cell2mat(yc');
Loop method (the better & fastest method)
This method works even when indices are not consecutive and have gaps.
x = [ 3 52 1
53 102 2];
y = zeros(1,max(max(x(:,[1,2]))));
for i = 1:size(x,1)
y(x(i,1):x(i,2)) = x(i,3);
end
  14 commentaires
Adam Danz
Adam Danz le 9 Mai 2019
Modifié(e) : Adam Danz le 9 Mai 2019
The median difference is less than 1 microsecond (0.00001 seconds).
Jebidiah Light
Jebidiah Light le 9 Mai 2019
BUT THE MICROSECONDS ADAM!!! Lol. I thought I reaccepted your answer earlier. Unless someone comes up with a better solution, I'm going to consider this matter closed. I really do appreciate all the time you have exhausted for this inquisition.

Connectez-vous pour commenter.

Plus de réponses (1)

Steven Lord
Steven Lord le 8 Mai 2019
This is complicated code, but it does satisfy the "one line, no loop" requirement. You will need to substitute 102 for the desired length of the vector and [3 53] with the first column of x.
y = cumsum(subsasgn(zeros(1, 102), substruct('()', {[3 53]}), 1))
You'd probably want to break it apart into pieces to understand what this line is doing, then add a paragraph of comments before putting this line in your code so the next person reading the code can understand it.
The phrase "for loop" is not (necessarily) a four letter word in MATLAB. Use for if it's the right tool for the job, use something else if that other tool is the right one.
  10 commentaires
Adam Danz
Adam Danz le 9 Mai 2019
My 3rd solution is listed first in the answer (just FYI).
Jebidiah Light
Jebidiah Light le 9 Mai 2019
Thanks Adam.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Matrix Indexing dans Help Center et File Exchange

Produits

Community Treasure Hunt

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

Start Hunting!

Translated by