1
$\begingroup$

Given a list (e.g. of integers) x and a list of 0s and 1s i (of the same length as x), how can I alter those entries of x where the value of i is 1?

For example, the code

n=10^8; x=RandomInteger[{-100,100},n]; i=RandomInteger[{0,1},n];
y=RandomInteger[{-100,100},n]; ByteCount@{x,i,y}
AbsoluteTiming@MaxMemoryUsed[i=Flatten[Position[i,1],1]]
AbsoluteTiming@MaxMemoryUsed[x[[i]]=y[[i]]]

shows that for 2.4GB of data, Position spends 22sec and 10GB, whilst assignment spends only 0.85sec and 0.8GB. The former seems excessive. Is there a better way to do this? Python has this built-in (when i is a numpy array of booleans).

$\endgroup$
4
  • $\begingroup$ why not just x = x (1 - i)? $\endgroup$
    – kglr
    Commented Oct 7, 2020 at 18:45
  • 2
    $\begingroup$ x[[Pick[Range@n,i,1]]=0 Code Wolfram like Wolfram, not Python, else it's Cobols all the way down... $\endgroup$
    – ciao
    Commented Oct 7, 2020 at 19:00
  • $\begingroup$ @kglr Uf, you're right, x=x*(1-i)+y*i. However, this only works if y is of the same length as x. But what if the length of y is the number of ones in i and I want to do x[[i]]=y? $\endgroup$
    – Leo
    Commented Oct 7, 2020 at 19:10
  • $\begingroup$ @Leo, posted the comment as an answer. $\endgroup$
    – kglr
    Commented Oct 7, 2020 at 19:43

1 Answer 1

1
$\begingroup$
n = 10^8; x = RandomInteger[{-100, 100}, n]; i = RandomInteger[{0, 1}, n];
z1 = z2 = z3 = x;

AbsoluteTiming @ MaxMemoryUsed[z1 = z1 (1 - i)]
{2.00115, 1600000424}
AbsoluteTiming @ MaxMemoryUsed[z3[[Random`Private`PositionsOf[i, 1]]] = 0]
{3.52455, 1599995920}
AbsoluteTiming @ MaxMemoryUsed[z2[[Pick[Range @ n, i, 1]]] = 0] (* ciao's comment*)
{4.8352, 1655914552}
z1 == z2 == z3
True

The last two also work for the case where "the length of y is the number of ones in i and I want to do x[[i]] = y".

$\endgroup$
2
  • $\begingroup$ Much appreciated! Just one more question: if Position and RandomPrivatePositionsOf do the same thing, but the latter is way more effective, why doesn't it replace the former as an official command? $\endgroup$
    – Leo
    Commented Oct 7, 2020 at 20:45
  • 1
    $\begingroup$ @Leo, Position handles arbitrary inputs' Random`Private`PositionsOf (seems to be ) limited to integer vectors. $\endgroup$
    – kglr
    Commented Oct 7, 2020 at 21:47

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.