BillyJean
BillyJean

Reputation: 1577

substituting matrix elements based on condition

I have the following example (that doesn't work!)

a(1, 1:2, 1:2) = [1 2; 3 4];
a(2, 1:2, 1:2) = [5 6; 7 8];

b=a;

for i=1:2
    b(a(i,:,:).*b(i,:,:) < 5.0) = 3*circshift(a(i,:,:), [1 0]);
end

So the idea is that all the places where a(i,:,:).*b(i,:,:) is less than five, b(i,:,:) should get the value of 3*circshift(a, [1 0]) at that place. Is that possible?

I can of course do it with a bunch of for-loops, but that doesn't seem like the most optimal solution.

Upvotes: 0

Views: 44

Answers (1)

Erik
Erik

Reputation: 4563

This is possible using the following:

b( (a.*b)<5 ) = [value you want];

Applied to your code:

a(1, 1:2, 1:2) = [1 2; 3 4];
a(2, 1:2, 1:2) = [5 6; 7 8];

b=a;

c = 3*circshift( a( (a.*b)<5 ), [1 0]); % first change a

b( (a.*b)<5 ) = c( (a.*b)<5 ); % then store c where (a.*b)<5 in b where (a.*b)<5

Notice I use (a.*b)<5 in a( (a.*b)<5 ). A command like x( condition ) = value; can be used to tell MATLAB to let x be value where condition is true. This is called logical indexing.

The same effect can be achieved with a for-loop, which can be easier to read for people that know some programming languages, but not MATLAB, but for-loops usually are slower than logical indexing. Another method would be using the find function to first find the indices of b where the condition (a.*b)<5 is true, then replacing those indices with the desired value. This too is slower than logical indexing and it needs more code.

Upvotes: 2

Related Questions