# Not[NumberQ] in ReplaceAll with PatternTest

I have a list that looks e.g.:

{1, 2, 3.2, "", "8", ""/1000}


i.e., a mixture of numbers, strings and mixture of strings and numbers. I want to replace everything that is not a number with "". After playing with Not and NumberQ and reading through here, I came up with

{1, 2, 3.2, "", "8", ""/1000} /. _?(Composition[Not, NumberQ]) -> ""


Which is, however not working, as the result is just "", but should be {1, 2, 3.2, "", "", ""} The wrong way round works:

   {1, 2, 3.2, "", "8", ""/1000} /. _?NumberQ -> ""


So how do I need to use 'Not' in here?

• The entire list {1, 2, ...} is not a number ;-) You might try Replace[{1, 2, 3.2, "", "8", ""/1000} , _?(Composition[Not, NumberQ]) -> "", {1}] to ensure that you're only working with elements of the list and not the entire list. Sep 11, 2018 at 9:28
• OK, I see this is working, but I'm a bit puzzled, as {1, 2, 3.2, "", "8", ""/1000} /. _?NumberQ -> "" works (although the wrong way round). I'll have to look into this in more detail. Thanks anyway! Sep 11, 2018 at 9:33
• This is easy enough to understand: {...} is not a number, so the replacement rule doesn't act on it. So next, ReplaceAll (/.) starts checking subparts of the expression. Sep 11, 2018 at 9:35
• BTW, a more idiomatic way of doing _?(Composition[Not, NumberQ]) is Except[_?NumberQ] Sep 11, 2018 at 9:38
• OK. Still not sure, but this is probably my lacking in some fundamentals. I thought /. means checking the Rule on each element of the list. At some point I have to buy a book that teaches the principles of Mathematica. Sep 11, 2018 at 9:50

The entire list {1, 2, ...} is not a number, therefore it is matched by the pattern

_?(Composition[Not, NumberQ])


and replaced with "" as whole. Here are a few possible approaches:

1. Act only on the elements of the list at level 1:

Replace[{1, 2, 3.2, "", "8", ""/1000} , _?(Composition[Not, NumberQ]) -> "", {1}]

2. Use the more idiomatic Except rather than composing with Not, either as above:

Replace[{1, 2, 3.2, "", "8", ""/1000} , Except[_?NumberQ] -> "", {1}]


or as

{1, 2, 3.2, "", "8", ""/1000} /. Except[_List, Except[_?NumberQ]] -> ""


The two-argument form of Except[] matches anything that is not the first argument, i.e. not a list, but that does match the second argument (i.e. Except[_?NumberQ]).

To address the confusion in the comments, the operator /. (ReplaceAll) works first on the entire expression, i.e. it first checks if the entire expression ({...}) matches the pattern. If it does not match, only then does it test its subparts (i.e. the elements of the list). If an element does not match and also has subparts, then it checks those subparts.