# Find positions of certain value in a big boolean list

I would like to know is it possible to find positions of False in t:

t = Table[RandomChoice[{True, False}], 6000];
Flatten[Position[t, False]] // AbsoluteTiming


faster than the above method. I will appreciate any help.

Speed here is hindered by the fact that True/False is not a packable type in Mathematica, although I personally think it should be.

If it is possible to reformulate your problem to use 1/0 instead, which can be packed, the methods already provided (Pick and SparseArray) each become much faster.

You can convert your data using With faster than using Boole, but the overhead is still significant:

SeedRandom[1]
t = Table[RandomChoice[{True, False}], 6000];

b = DeveloperToPackedArray @
With[{True = 1, False = 0}, Evaluate @ t]; // RepeatedTiming

{0.000151, Null}


Now observe how fast Pick becomes compared to its direct application on t:

r1 = Pick[Range @ Length @ t, t, False]; // RepeatedTiming

r2 = Pick[Range @ Length @ b, b, 0]; // RepeatedTiming

r1 === r2

{0.000343, Null}

{0.0000509, Null}

True


Combined with the overhead of the conversion this is a little slower than kglr's method (0.000176 second on my machine), but it gives an idea of the performance that is possible if you can avoid True/False and use packed integers instead.

• Wow, I am really surprised that With[{True = 1, False = 0}, Evaluate @ t] is faster than Boole. – Henrik Schumacher Aug 10 '18 at 6:54
• @Henrik It's kind of disappointing isn't it? – Mr.Wizard Aug 10 '18 at 14:58
• Yes, it is... As well as the general slowness of Booleans in Mathematica. – Henrik Schumacher Aug 10 '18 at 20:06
• @Henrik Yet another case where there is room for improvement in the core language that is neglected, all the while new functions applicable only for some are added. – Mr.Wizard Aug 10 '18 at 20:20
• sigh I am totally with you in that respect. – Henrik Schumacher Aug 10 '18 at 20:21

You can use Pick:

t = Table[RandomChoice[{True,False}],6000];
r1 = Flatten[Position[t,False]]; //RepeatedTiming
r2 = Pick[Range@Length@t,t,False]; //RepeatedTiming

r1 === r2


{0.0023, Null}

{0.00036, Null}

True

Another useful alternative is PositionIndex, especially when you want to know the positions of different values:

r3 = PositionIndex[t]; //RepeatedTiming

r1 === r2 === r3[False]


{0.00070, Null}

True

Using SparseArray with "AdjacencyLists" or with "NonzeroPositions" is faster than alternatives posted so far:

SeedRandom[1]
t = Table[RandomChoice[{True, False}], 6000];

r4 =SparseArray[t, Automatic, True]["AdjacencyLists"]; //RepeatedTiming  // First


0.00021

r5 = Flatten@SparseArray[t, Automatic, True]["NonzeroPositions"]; //RepeatedTiming// First


0.00021

versus

r1 = Flatten[Position[t, False]]; // RepeatedTiming // First


0.0027

r2 = Pick[Range @ Length @ t, t, False]; // RepeatedTiming // First


0.000414

r3 = PositionIndex[t][False]; // RepeatedTiming // First


0.000830

(b = DeveloperToPackedArray @ With[{True =1, False =0}, Evaluate @ t];
r6 = Pick[Range @ Length @ b, b, 0];) //RepeatedTiming  // First


0.00028

SameQ[r1, r2, r3, r4, r5, r6]


True

where r1 is from OP, r2 and r3 are from Carl Woll's and r6 is from Mr.Wizard's answer.