Filter löschen
Filter löschen

How to avoid for nested loops with if condition?

2 Ansichten (letzte 30 Tage)
Mantas Vaitonis
Mantas Vaitonis am 25 Jun. 2018
Kommentiert: Mantas Vaitonis am 26 Jun. 2018
Hello,
I have big matrixes of same size, and am suing for loop with if statement, which is bottleneck in my code and is very slow. How would it be possible to optimize it?
for i=1:n1
for j=1:n2
if id(i,j)==1
if RR(i,j)==1
id(i,x(i,j))=0;
end
end
end
end
Maybe it is possible to vectorize or use bsxfun?

Akzeptierte Antwort

Guillaume
Guillaume am 25 Jun. 2018
Bearbeitet: Guillaume am 25 Jun. 2018
You certainly don't need the j loop:
for row = 1:size(id)
id(row, x(id(row, :) == 1 & RR(row, :) == 1)) = 0;
end
You could get rid of the i loop as well at the expense of memory (another array the same size as id)
mask = id == 1 & RR == 1; %and if id and RR are logical, simply: mask = id & RR;
rows = repmat((1:size(id, 1)', 1, size(id, 2));
id(sub2ind(size(id), rows(mask), x(mask))) = 0;
  10 Kommentare
Guillaume
Guillaume am 26 Jun. 2018
So it's replicated pairs in a single row that need to be removed, no replicated pairs across the whole matrix. If so, you can indeed use a loop over the rows as you've done but yours is overcomplicated and your transition through a 3d matrix only works by accident (your cat(3,...) is reshaped into a 2d matrix). This would be simpler:
x = [3 1 1 5 3;2 1 1 5 3];
a = repmat([1 2 3 4 5], size(x, 1), 1);
for row = 1:size(x, 1)
[~, tokeep] = unique(sort([x(row, :)', a(row, :)'], 'rows', 'stable');
a(row, setdiff(1:size(a, 2), tokeep) = 0;
end
Now, there is a way to do it without a loop. It's pretty hairy, having to go through a 4D matrix:
x = [3 1 1 5 3;2 1 1 5 3];
a = repmat([1 2 3 4 5], size(x, 1), 1);
sortedpairs = sort(cat(3, x, a), 3);
matchedpairs = all(sortedpairs == permute(sortedpairs, [1 4 3 2]), 3);
matchnotfirst = cumsum(matchedpairs, 2) > 1 & matchedpairs; %only keep 2nd and subsequent pair
toreset = any(matchnotfirst, 4);
a(toreset) = 0
Mantas Vaitonis
Mantas Vaitonis am 26 Jun. 2018
Thank You, greate now it wokrs as it should, without for loop.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Nithin Banka
Nithin Banka am 25 Jun. 2018
I don't think you need to use 'for' loop. The 2 'if' statements can be easily handled in MATLAB.
index_of_1_in_id_and_RR = (id==1&RR==1); %valid as you told they have same size
You can use this variable in further steps.
  3 Kommentare
Nithin Banka
Nithin Banka am 25 Jun. 2018
Can you provide me 'x'?
Mantas Vaitonis
Mantas Vaitonis am 25 Jun. 2018
Yes, for example all arrays are same size (5x5), RR,id and x. Values inside arrays can be in random 1:5 type double. Like x can be [5 3 1 1 2;....]

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Entering Commands finden Sie in Help Center und File Exchange

Community Treasure Hunt

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

Start Hunting!

Translated by