3

Imagine we have:

a = RandomInteger[1, {50, 150, 53}];
b = RandomInteger[1, {50, 150, 53}];
mask = RandomInteger[1, {50, 150, 53}];

How do I replace a(mask) with b(mask)?

JEM_Mosig
  • 3,003
  • 15
  • 28
user49047
  • 791
  • 5
  • 17

2 Answers2

8

If mask may contain only zeros and ones, then you can do such assignment arithmetically:

(b - a)*mask + a

Since arithmetic operations on arrays are highly optimized, this solution should be quite fast:

(b - a)*mask + a; // RepeatedTiming // First

0.000885

Ray Shadow
  • 7,816
  • 1
  • 16
  • 44
7

One way to do this when a and b may contain any kind of symbolic expression could be

With[{pos = Position[mask, 1]},
  ReplacePart[a, Thread[pos -> Extract[b, pos]]]
]

Here, first you get the positions at which mask contains 1. Then, you replace every part of a at these positions with the corresponding entry of b at this position.

Assuming a, b, and mask only contain 0 or 1 you can use the much faster solution:

a - BitAnd[a, mask] + BitAnd[b, mask]

or, even faster:

BitOr[BitAnd[a, BitNot[mask]], BitAnd[b, mask]]

Here are the timings in comparison:

a - BitAnd[a, mask] + BitAnd[b, mask] // RepeatedTiming // First
(* 0.012 *)

BitOr[BitAnd[a, BitNot[mask]], BitAnd[b, mask]] // RepeatedTiming // First
(* 0.0075 *)

the latter being even faster than @Shadowray's solution:

(b - a)*mask + a // RepeatedTiming // First
(* 0.0098 *)
JEM_Mosig
  • 3,003
  • 15
  • 28