4
$\begingroup$

Let's say we want a pattern, that matches, when expression contains some terms but it can optionaly contain some other terms. For example:

Cases[
{-x^2 + Log@x + Sin@x, 3.14 x^2 + Log@x, x^2, x^2 + Tan@x},

(((_?NumericQ)x^2|x^2) + Log@x + Sin@x)|
(((_?NumericQ)x^2|x^2) + Log@x)|
(((_?NumericQ)x^2|x^2) +  Sin@x)|
(((_?NumericQ)x^2|x^2))
]

Out:

{-x^2 + Log[x] + Sin[x], 3.14 x^2 + Log[x], x^2}

In this example expression has to contain $a x^2$, but it can also contain $\sin(x)$ and $\ln(x)$. In my real example, I have $6$ optional terms, meaning, I would have to write $2^6=64$ versions.

Instead I would like to do something like this, where NothingP woluld be equivalent of Nothing for patterns:

Cases[
{-x^2 + Log@x + Sin@x, 3.14 x^2 + Log@x, x^2, x^2 + Tan@x},
(((_?NumericQ)x^2|x^2) + (Log@x|NothingP) + (Sin@x|NothingP))
]

So is there such a command/ another way to do it? I can't find it in a documentation.

Also a side question: is there a short form of ((_?NumericQ)x^2|x^2) ?

$\endgroup$
9
  • 1
    $\begingroup$ For the short form of ((_?NumericQ)x^2|x^2) there is _.x^2. Basically _.*expression means that the expression is multiplied by something or 1. Also _.+expression means expression plus something or 0. You can check OneIdentity and Default for more details. $\endgroup$ Sep 16, 2022 at 12:48
  • 1
    $\begingroup$ Correcting my deleted comment: I am not sure how general or abstract you would like the solution to be but in the case you gave you could use the pattern Alternatives[_.*x^2 + __?(MemberQ[{Log[x], Sin[x]}, #] &), x^2] (Notice the double blank) $\endgroup$ Sep 16, 2022 at 13:12
  • $\begingroup$ Thanks, that is exactly what I Needed. Alternatives[.*x^2 + __?(MemberQ[{Log[x], Sin[x]}, #] &), x^2] works. But how to use the _.+ expression? _.*x^2 +. Log[x]_.+Sin[x] doesn't work. $\endgroup$ Sep 16, 2022 at 13:19
  • 1
    $\begingroup$ Like for example Cases[{r, s, n + r} , _. + r]. $\endgroup$ Sep 16, 2022 at 14:00
  • 1
    $\begingroup$ Thank you for accepting my answer but it could be better to wait a day or two until someone finds an answer to your original question, meaning to find a pattern object that acts like Nothing $\endgroup$ Sep 16, 2022 at 14:16

2 Answers 2

5
$\begingroup$

You could use Repeated[..., {0,1}] to match elements which may appear zero or one times, but there's even better option in this case, that is, Optional.

Cases[{-x^2 + Log@x + Sin@x, 3.14 x^2 + Log@x, x^2, x^2 + Tan@x},
 (a_. x^2 /; NumericQ[a]) + Optional[sin : Sin[x], 0] + 
  Optional[log : Log[x], 0]]

(* {-x^2 + Log[x] + Sin[x], 3.14 x^2 + Log[x], x^2} *)

This way you don't need to special-case the form for x^2. I'm not entirely certain I find the explicit description of interaction of Optional, Default and OneIdentity for Plus (which is of course 0) in the documentation, but nonetheless, this works.

This syntax, with unnecessary pattern name is a bit odd, in my opinion. It can be also written as:

Cases[{-x^2 + Log@x + Sin@x, 3.14 x^2 + Log@x, x^2, x^2 + Tan@x},
 (a_. x^2 /; NumericQ[a]) + (sin : Sin[x] : 0) + (log : Log[x] : 0)]

Technically, what you refer as NothingP is PatternSequence[]. The problem with this form is that it doesn't have a default value, and thus doesn't interact very gracefully with Plus in this case.

$\endgroup$
3
$\begingroup$

The comment section got a bit long and as it would be tedious for someone else to read through the comments I moved my last comment, that only solves this specific situation, to an answer.

I had never used this kind of pattern matching before but using the answer I found here, it seems that, for the specific problem at hand, instead of using a pattern that has the properties of Nothing you can use the code below (in the pattern that follows b is just a name that can be replaced with another symbol)

 _.*x^2 + b : (__?(MemberQ[{Log[x], Sin[x]}, #] &)) : 0

Example:

    Cases[{-x^2 + Log@x + Sin@x, 3.14 x^2 + Log@x, x^2, 
  x^2 + Tan@x}, _.*x^2 + 
  b : (__?(MemberQ[{Log[x], Sin[x]}, #] &)) : 0]

Output: (* {-x^2 + Log[x] + Sin[x], 3.14 x^2 + Log[x], x^2} *)

$\endgroup$
1
  • $\begingroup$ I noticed after @kirma's answer that I should have included a NumericQ restriction. Using the syntax above one could replace _.*x^2 with (g : _?NumericQ : 0)*x^2 where g can be exchanged with another name. $\endgroup$ Sep 16, 2022 at 19:28

Your Answer

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

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