3
$\begingroup$

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)?

$\endgroup$
0

2 Answers 2

7
$\begingroup$

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 *)
$\endgroup$
8
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ I think this gives a wrong result. Try, e.g., a = ConstantArray[ 1, {2, 3}]; b = {{1, 1, 1}, {0, 0, 0}}; mask = {{1, 0, 0}, {0, 1, 1}}; $\endgroup$ Commented Jul 11, 2017 at 21:30
  • $\begingroup$ @JEM_Mosig I have corrected the answer (exchanged a and b) $\endgroup$ Commented Jul 11, 2017 at 21:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.