Andreas
Andreas

Reputation: 7550

Change values in a matrix non-destructively

Assume that B is some large matrix with integers, both zero and non-zero. I want to call the function my_function with B as an argument, but with the zero-values set to 1. Is there a way to do that without creating a temporary variable, as A in this case?

A = B;
A(A==0) = 1;
my_function( A ); 

Upvotes: 2

Views: 91

Answers (4)

Eitan T
Eitan T

Reputation: 32930

Actually, in this specific case it is possible with the expression B + ~B.

Example

>> B = fix(5 * rand(5))

B =
  4  0  3  2  3
  0  3  3  0  2
  1  4  0  0  2
  1  4  3  4  3
  3  1  1  1  1

>> B + ~B

ans =
  4  1  3  2  3
  1  3  3  1  2
  1  4  1  1  2
  1  4  3  4  3
  3  1  1  1  1

There you go.

Upvotes: 4

angainor
angainor

Reputation: 11810

Since you seem to be concerned about the memory consumption, the short answer is - no. Matlab uses explicit index variables for about everything. What others suggested before:

idx = find(B==0)

silently allocates a matrix of size(B) logical values for the expression B==0. Depending on the matlab version, logical type may be 4 bytes or 1 byte, which saves you some memory compared to creating a copy of B:

A = B;

However, find again returns an array of doubles. Hence, depending on how many non-zero entries you actually have in B, you may end up using a lot of RAM: you need the memory to store B==0, and the memory to store the result of find at the same time.

So, depending on your problem, it may be actually cheaper memory-wise to just to a copy of the variable.

Upvotes: 1

Oli
Oli

Reputation: 16045

Matlab does not really allows to do that.

But you can use the following simple trick:

idx=find(B==0);
B(idx) = 1;
my_function(B); 
B(idx) = 0;

Upvotes: 1

jerad
jerad

Reputation: 2028

No, if you want to retain a copy of the original B, then you will have to make a second variable. Either duplicate it as you are doing, or replace the 0s with 1s after storing the indices to those elements in a second variable, i.e.

idx    = find(B==0);
B(idx) = 1;

If numel(idx) is considerably smaller than numel(B), then that would save you some memory overhead if that's your concern.

Upvotes: 0

Related Questions