Nested loop problem with the second index

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.

 Akzeptierte Antwort

Jan
Jan am 2 Jul. 2019
Bearbeitet: Jan am 2 Jul. 2019

1 Stimme

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 Kommentar

Jan
Jan am 2 Jul. 2019
Bearbeitet: Jan am 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.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Torsten
Torsten am 2 Jul. 2019
Bearbeitet: Torsten am 2 Jul. 2019

0 Stimmen

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 am 2 Jul. 2019
Bearbeitet: Stephen23 am 2 Jul. 2019

0 Stimmen

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

Kategorien

Mehr zu Matrices and Arrays finden Sie in Hilfe-Center und File Exchange

Produkte

Tags

Gefragt:

am 2 Jul. 2019

Bearbeitet:

Jan
am 2 Jul. 2019

Community Treasure Hunt

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

Start Hunting!

Translated by