Suppose I have a list called mask
composed of 1,2,3,...n. n is different in different situation. Let me takes n=3 for demonstration
mask=RandomInteger[{1,3},1000000]
and another list
list = RandomReal[{0, 1}, 1000000];
I want to pick those element corresponding not equal to 1.
Pick[list, mask, _?(# != 1 &)]; // Timing
This takes 1.125 sec
But If I already know mask
only composed of 1,2,3, then this
Pick[list, mask, 2 | 3]; // Timing
is faster, it takes 0.25 sec
But the problem is I am not sure that is in mask
, so this is not general.
So the question is there more efficient way than this _?(# != 1 &)
pattern? Why is it slower then pattern 2|3
?
2|3
is faster than_?(# != 1 &)
: it's because the latter involves evaluating Mathematica code (evaluating the pure function) for each test. The former doesn't. $\endgroup$Pick[list, mask, Except[1]]
but it fails because theExcept
matches the whole list.Pick[list, mask, Except[1, _Integer]]
works and is the same speed as2 | 3
. $\endgroup$2|3
doesn't evaluate for each test? Then how can it know which one to pick? $\endgroup$_?(# != 1 &)
you'd need a callback to the main evaluator (i.e. run Mathematica code) for each test. For2|3
you don't. You just need to test for equality between2
(or3
) and the given list element, but this test doesn't involve running Mathematica code. It can be done only in C. $\endgroup$