I have a vector A =[ 1;3;1;4] and a vector B = [ 8,9,9,6]. The values of A must increase one by one till reaching the value speficied in B, then, how can I obtain the following matrix:
[1 2 3 4 5 6 7 8 0; 3 4 5 6 7 8 9 0 0; 1 2 3 4 5 6 7 8 9; 4 5 6 0 0 0 0 0 0]
without using a for loop?
Thank your very much for your help

 채택된 답변

Star Strider
Star Strider 2017년 1월 8일

2 개 추천

This creates your matrix with an expressed loop, however there are obviously loops within the functions.
The Code
A = [ 1;3;1;4];
B = [ 8,9,9,6];
C = ones(size(A,1), max(B));
C = cumsum(C,2);
C = bsxfun(@plus, C, A-1);
I = bsxfun(@le, C, B(:));
C = C.*I % Desired Result
C =
1 2 3 4 5 6 7 8 0
3 4 5 6 7 8 9 0 0
1 2 3 4 5 6 7 8 9
4 5 6 0 0 0 0 0 0
The ‘C’ matrix is (obviously) the output.

댓글 수: 6

Star Strider
Star Strider 2017년 1월 8일
Jose Luis’s ‘Answer’ moved here:
Thank you for your answer, that works. It seems to be a little long, is there any faster way of doing this?
My pleasure.
A 5-line solution to your problem is long?
That 5-line solution to your problem is the most efficient approach without a loop (that you wrote you wanted to avoid) that exists, and a loop would be less efficient. You could combine the first two lines into one (creating a 4-line solution):
C = cumsum(ones(size(A,1), max(B)),2);
but I doubt that would significantly speed my code. I kept the lines separate in order to make my code easier to read and understand. The rest of the code must remain as it is.
It is fast, because bsxfun is very efficient, and faster than many alternative approaches to do the same things.
If my Answer solves your problem, please Accept it!
Slight correction to Star's code. It should be:
C = ones(size(A, 1), max(B(:) - A(:) + 1));
C = cumsum(C, 2);
or
C = cumsum(ones(size(A, 1), max(B(:) - A(:) + 1)), 2);
Star Strider
Star Strider 2017년 1월 8일
Thank you, Guillaume.
My code does work, as posted. Your changes make it more robust, an important consideration. (I was just happy to get the logic working correctly yesterday!)
Jose Luis
Jose Luis 2017년 1월 11일
편집: Star Strider 2017년 1월 11일
Thank you very much for your help. I was a little afraid of two bsxfun functions taking too much time, but after comparing with the alternatives proposed by Guillaume it seems to be the best (faster) way of doing this task . Indeed, the correction proposed by Guillaume does improve the code as it doesn't append zeros at the end of the matrix, so that the final code is:
C = cumsum(ones(size(A, 1), max(B(:) - A(:) + 1)), 2);
C = bsxfun(@plus, C, A-1);
I = bsxfun(@le, C, B(:));
C = C.*I
Star Strider
Star Strider 2017년 1월 11일
As always, my pleasure!

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Guillaume
Guillaume 2017년 1월 8일

1 개 추천

There is nothing wrong with using loops when they make the code clearer. This is, arguably, the most efficient loop version:
C = zeros(numel(A), max(B(:) - A(:)) + 1);
for row = 1:numel(A)
C(row, 1:B(row)-A(row)+1) = A(row):B(row);
end
Another option, not using explicit loops, shorter but probably far less efficient than Star's answer:
ncols = max(B(:) - A(:)) + 1;
C = cell2mat(arrayfun(@(s, e) [s:e, zeros(1, ncols-e+s-1)], A, B(:), 'UniformOutput', false))

댓글 수: 1

Star Strider
Star Strider 2017년 1월 11일
Guillaume, thank you for the corrections to my code.
+1

댓글을 달려면 로그인하십시오.

카테고리

도움말 센터File Exchange에서 Loops and Conditional Statements에 대해 자세히 알아보기

질문:

2017년 1월 8일

댓글:

2017년 1월 11일

Community Treasure Hunt

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

Start Hunting!

Translated by