10
$\begingroup$
Pick[{1, 2}, {0, 1}, Except[0]]

returns {1, 2}, the first element of which I did expect to be excluded. What is the thing I don't understand?!

$\endgroup$
1

2 Answers 2

10
$\begingroup$

This works:

Block[{Pick}, Thread@Pick[{1, 2}, {0, 1}, Except[0]]]

This is due to the fact that Pick[1,0,Except[0]] also works and gives Sequence[]. It appears, the pattern is working first on the whole expression. As {0, 1} matches Except[0], it gives true and the corresponding element is the entire list {1, 2}.

Another quick workaround is this:

Pick[{1, 2}, {0, 1}, Except[0, Except[_List]]]

Here's a test to illustrate my PS:

Pick[{1, 2*x}, {0, x + 2}, Except[0, patt_ /; AtomQ[patt]]]

The internal forms of the list and selector are:

{1, Times[2,x]}
{0, Plus[2,x]}

As you can see, the nesting of the structures is identical, but the heads differ. Nonetheless, Pick disregards the fact that Times and Plus are not the same and returns {2 x}. IMO, maybe Pick is in over its head with generality.

PS As Szabolcs comments, this was already discussed in the dupe + linked Q. I might add to the discussion, that since Pick is a very general function, that's designed to work on (1) arbitrarily shaped nested structures, and (2) the heads of which are not necessarily List, there is some logic, that the easy way out is to go through a top-level first, complete-expression first search routine. It, of course, has some caveats, such as this one.

$\endgroup$
5
  • $\begingroup$ +1 So Except does work. It's just thrown by the sequence functionality. $\endgroup$ Commented Apr 26, 2016 at 14:35
  • 8
    $\begingroup$ Pick[{1, 2, 3, 4}, {0, 1, 0, 2}, Except[0 | _List]] also works. (+1) $\endgroup$
    – kglr
    Commented Apr 26, 2016 at 14:36
  • $\begingroup$ As does Pick[{1, 2, 3, 4}, {0, 1, 0, 2}, Except[0, _Integer]] $\endgroup$
    – user1066
    Commented Apr 26, 2016 at 16:54
  • $\begingroup$ @kglr Your comment received 7 upvotes. Please turn your comment into an answer. $\endgroup$
    – QuantumDot
    Commented May 17, 2016 at 9:23
  • $\begingroup$ @QuantumDot The thread has been closed, as you can see. I agree, that Except[0 | _List] is cleaner than Except[0, Except[_List]]. If you feel sufficiently strongly about this, you're welcome to edit it into the answer. $\endgroup$
    – LLlAMnYP
    Commented May 17, 2016 at 10:13
3
$\begingroup$

Looks like Except doesn't work in Pick pattern matching. Here's a workaround.

Pick[{1, 2, 3, 4}, {0, 1, 0, 2}, _?(# != 0 &)]

{2, 4}

Or similar to the form in Pick: Possible Issues (last example)

list = {1, 2, 3, 4};
selector = {0, 1, 0, 2};
newSelector = Map[MatchQ[#, Except[0]] &, {0, 1, 0, 2}];
Pick[list, newSelector]

{2, 4}

$\endgroup$

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