Nested loop problem with the second index

2 views (last 30 days)
gianluca
gianluca on 2 Jul 2019
Edited: Jan on 2 Jul 2019
Dear all,
the following code does not work well for index j > 1. I have two vectors cpx = 1-by-n and cpy = 1-by-m.
I would a new matrix cp with n-by-m rows and 2 columns with all the possible permutations of the elements in cpx and cpy. Where is the mistake?
for i = 1:length(cpx)
for j = 1:length(cpy)
cp(i.*j,:) = [cpx(i) cpy(j)];
end
end
The results are fine till row 55, so that the first cicle for i = 1:55 and j = 1 works well, then the results are incomprehensible.

Accepted Answer

Jan
Jan on 2 Jul 2019
Edited: Jan on 2 Jul 2019
The problem of you code was cp(i.*j,:). i*j is not a growing index. In the 1st iteration 1*1 is fine. For i=1 it works for the complete loop over j. But in the next iteration for i=2, j=1 you overwrite the value written by i=1, j=2. Better:
nx = numel(cpx);
ny = numel(cpy);
cp = zeros(nx * ny, 2); % Pre-allocation!!!
for i = 1:nx
for j = 1:ny
cp((i-1) * ny + j,:) = [cpx(i) cpy(j)];
end
end
But this can be written without loops:
cp = [repelem(cpx(:), numel(cpy), 1), repmat(cpy(:), numel(cpx), 1)];
  1 Comment
Jan
Jan on 2 Jul 2019
Edited: Jan on 2 Jul 2019
Some timings:
cpx = rand(1000, 1);
cpy = rand(1000, 1);
tic
cp = zeros(length(cpx)*length(cpy),2);
row = 0;
for i = 1:length(cpx)
for j = 1:length(cpy)
row = row + 1;
cp(row,:) = [cpx(i) cpy(j)];
end
end
toc
% 6.8 sec
tic;
[X,Y] = ndgrid(cpx,cpy);
M = [X(:),Y(:)];
toc
% 0.018 sec
tic;
nx = numel(cpx);
ny = numel(cpy);
cp = zeros(nx * ny, 2);
for i = 1:nx
for j = 1:ny
cp((i-1) * ny + j,:) = [cpx(i) cpy(j)];
end
end
toc
% 3.9 sec
tic
cp = [repmat(cpx(:), numel(cpy), 1), repelem(cpy(:), numel(cpx), 1)];
toc
% 0.022 sec
For 100x1 inputs, REPELEM/REPMAT is faster than NDGRID. For arrays > 1000 elements, NDGRID is faster - to my surprise, because it uses REPMAT twice also. In every case, they outperform the loops massively.

Sign in to comment.

More Answers (2)

Torsten
Torsten on 2 Jul 2019
Edited: Torsten on 2 Jul 2019
cp = zeros(length(cpx)*length(cpy),2);
row = 0;
for i = 1:length(cpx)
for j = 1:length(cpy)
row = row + 1;
cp(row,:) = [cpx(i) cpy(j)];
end
end

Stephen23
Stephen23 on 2 Jul 2019
Edited: Stephen23 on 2 Jul 2019
The simple MATLAB way:
>> cpx = [1,3,5,7];
>> cpy = [22,44,66];
>> [X,Y] = ndgrid(cpx,cpy);
>> M = [X(:),Y(:)]
M =
1 22
3 22
5 22
7 22
1 44
3 44
5 44
7 44
1 66
3 66
5 66
7 66

Categories

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

Tags

Products

Community Treasure Hunt

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

Start Hunting!