5
$\begingroup$

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?

$\endgroup$
6
  • 2
    $\begingroup$ 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. $\endgroup$
    – LLlAMnYP
    Sep 11, 2018 at 9:28
  • $\begingroup$ 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! $\endgroup$ Sep 11, 2018 at 9:33
  • 1
    $\begingroup$ 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. $\endgroup$
    – LLlAMnYP
    Sep 11, 2018 at 9:35
  • $\begingroup$ BTW, a more idiomatic way of doing _?(Composition[Not, NumberQ]) is Except[_?NumberQ] $\endgroup$
    – LLlAMnYP
    Sep 11, 2018 at 9:38
  • $\begingroup$ 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. $\endgroup$ Sep 11, 2018 at 9:50

1 Answer 1

8
$\begingroup$

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.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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