How to use `Except[]` inside of `Pick[]`

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.


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}