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 件のコメント

Adam Danz
Adam Danz 2019 年 5 月 8 日
Problem 1: you haven't explained the transformation. How do you get from x to y (in words)?
Problem 2: x seems to be a [2-by-3] matrix. What is the size of y? It has missing values so is it a cell array?
Jebidiah Light
Jebidiah Light 2019 年 5 月 8 日
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 2019 年 5 月 8 日
編集済み: Adam Danz 2019 年 5 月 8 日
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...

サインインしてコメントする。

 採用された回答

Adam Danz
Adam Danz 2019 年 5 月 8 日
編集済み: Adam Danz 2019 年 5 月 9 日

3 投票

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 件のコメント

madhan ravi
madhan ravi 2019 年 5 月 8 日
The thing is OP wants no loop that’s where I am puzzled at.
Adam Danz
Adam Danz 2019 年 5 月 8 日
Ah, just saw that in the title.
Jebidiah Light
Jebidiah Light 2019 年 5 月 8 日
I can write this with a loop. that's easy. I want to do it without a loop. I don't think it's possible but I figured I'd ask.
Adam Danz
Adam Danz 2019 年 5 月 8 日
編集済み: Adam Danz 2019 年 5 月 8 日
There you go! You had me at "I don't think it's possible". :)
(I updated my answer)
madhan ravi
madhan ravi 2019 年 5 月 8 日
I have seen somewhere that Andrei has once proposed a solution for this kind of problem without loop or mat2cell() but cannot find it at the moment.
Jebidiah Light
Jebidiah Light 2019 年 5 月 8 日
I know it's silly. My boss wants this without a loop. I told my boss that a loop was best but...
Adam Danz
Adam Danz 2019 年 5 月 8 日
編集済み: Adam Danz 2019 年 5 月 8 日
Well, now you've got it! Gotta make the boss happy. (FYI, I just updated my answer with a small change to avoid potential problems).
Jebidiah Light
Jebidiah Light 2019 年 5 月 8 日
Thanks that definitly works. Now, to show my boss how much longer no loop takes than a simple loop.
Adam Danz
Adam Danz 2019 年 5 月 8 日
Ha!
Disclaimer: My no-loop method might not be the fastest possible no-loop method.
Adam Danz
Adam Danz 2019 年 5 月 8 日
@Jebidiah Light, I updated my no-loop code so that it works when the indices are not consecutive. For example,
x = [ 3 52 1 %52 is not consecutive to 60
60 102 2];
The newer version is slightly cleanear anyway.
Adam Danz
Adam Danz 2019 年 5 月 9 日
編集済み: Adam Danz 2019 年 5 月 9 日
@Jebidiah Light, following the discussion under Steven Lord's answer, I added a 3rd solution that's a one-liner and assumes that indices are consecutive and without gaps. You're not going to get much simpler than that.
I ran a speed test on this new method vs. the for-loop where each were run 100,000 times and they are almost indistinguisable but on average, the for-loop is still ~1.5 times faster (p<0.001, Wilcox signed rank).
It's kind of an old-school mentality that for-loops can always be beat by a different method.
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
I absolutely agree with you Adam. :D
Adam Danz
Adam Danz 2019 年 5 月 9 日
編集済み: Adam Danz 2019 年 5 月 9 日
The median difference is less than 1 microsecond (0.00001 seconds).
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
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.

サインインしてコメントする。

その他の回答 (1 件)

Steven Lord
Steven Lord 2019 年 5 月 8 日

3 投票

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 件のコメント

madhan ravi
madhan ravi 2019 年 5 月 8 日
Thank you :)
Adam Danz
Adam Danz 2019 年 5 月 8 日
編集済み: Adam Danz 2019 年 5 月 8 日
Really interesting. While digging into it, I realized that both of our no-loop approaches would break if the indices were not consecutive. For example,
x = [ 3 52 1
60 102 2]; %52 not consecutive with 60
I updated my no-loop solution so that it works with discontinuous indices.
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
Adam I like that you're thinking about Consecutiveness.Steven, your codes conciseness is awe-inspiring. But, after testing both, we are still not there yet. Columns 1:2 will always be consecutive; however, column 3 will not. Let me give you another example of what x can look like.
x =
103 602 5
603 1102 11
1103 1602 26
1603 2102 34
2103 2602 39
2603 3102 42
3103 3602 43
3603 4102 55
4103 4602 56
4603 5102 59
5103 5602 67
5603 6102 68
6103 6602 78
6603 7102 79
7103 7602 96
7603 8102 98
Adam Danz
Adam Danz 2019 年 5 月 9 日
編集済み: Adam Danz 2019 年 5 月 9 日
@Jebidiah Light, maybe you're not using my most recent version (I added a comment under my answer yesterday to let you know I updated it).
When I run the for-loop and my no-for-loop versions, they produce the same results. Neither version depend on there being any consecutive values in any column of x.
x = [
103 602 5
603 1102 11
1103 1602 26
1603 2102 34
2103 2602 39
2603 3102 42
3103 3602 43
3603 4102 55
4103 4602 56
4603 5102 59
5103 5602 67
5603 6102 68
6103 6602 78
6603 7102 79
7103 7602 96
7603 8102 98 ];
% For loop method
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
% no for loop method
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);
y2 = zeros(1,max(max(x(:,[1,2]))));
y2(cell2mat(xIdx')) = cell2mat(yc');
% Compare results
isequal(y,y2)
% ans =
% logical
% 1
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
Sorry Adam, I didn't explain well. Your code works and is beautifully written. The issue is it's still less efficient than a for loop. My boss said we can’t use it unless it takes less time to run. Steven's code is more efficient than using a for loop but only inputs 1's and 2's.
Adam Danz
Adam Danz 2019 年 5 月 9 日
編集済み: Adam Danz 2019 年 5 月 9 日
Check out my new answer (assumes that indices are consecutive and do not have gaps).
Steven Lord
Steven Lord 2019 年 5 月 9 日
I suspect I know what you want with the data you posted, but can you clearly state (in words) exactly what each column of x represents and how it relates to the desired output? If possible give us a clear recipe rather than feeding us a sample cookie and asking us to make one just like it.
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
I apologize Steven. Adams’s 3rd solution meets every criterion except efficiency, when compared to a for loop. I will try my best to explain this better. 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.
Adam Danz
Adam Danz 2019 年 5 月 9 日
My 3rd solution is listed first in the answer (just FYI).
Jebidiah Light
Jebidiah Light 2019 年 5 月 9 日
Thanks Adam.

サインインしてコメントする。

カテゴリ

ヘルプ センター および File ExchangeVariables についてさらに検索

製品

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by