MatchQ[x y, (x | y) (x | y)]

It returns false. Why?

I want to eliminate terms like x^2, y^2, z^2, x y, x z, y z.

  • 11
    $\begingroup$ I think because (x | y) (x | y) evaluates to (x | y)^2, which doesn't match your expression. $\endgroup$
    – march
    Jun 13, 2016 at 4:04
  • $\begingroup$ What do you mean by "I want to eliminate terms like x^2, y^2, z^2, x y, x z, y z"? $\endgroup$
    – xzczd
    Jun 13, 2016 at 4:04
  • 1
    $\begingroup$ Does MatchQ[#, _^2 | a_ b_] & /@ {x^2, y^2, z^2, x y, x z, y z} do what you want? Your post needs more information, because there is an inconsistency between the terms you want to eliminate and the patterns you are making. Do you want to eliminate any second-degree monomial? Or do you want to eliminate any second-order monomial that involves x or y? (or x or y and nothing else)? $\endgroup$
    – march
    Jun 13, 2016 at 4:06
  • 6
    $\begingroup$ Btw: MatchQ[x y, HoldPattern[(x | y) (x | y)]] $\endgroup$
    – Kuba
    Jun 13, 2016 at 8:22
  • 1
    $\begingroup$ For more info, the reason @Kuba 's method works is to avoid the problem march mentioned. $\endgroup$
    – QuantumDot
    Jun 13, 2016 at 9:19

3 Answers 3


If you Trace the evaluation sequence of this expression, you get the following:

Trace@MatchQ[x y, (x | y) (x | y)]
(* {{(x|y) (x|y), (x|y)^2}, MatchQ[x y, (x|y)^2], False} *)

This shows that (x|y) (x|y) gets evaluated to (x|y)^2 before the pattern matching occurs, and x y doesn't match (x|y)^2, although x^2 and y^2 will:

MatchQ[#, (x | y) (x | y)] & /@ {x^2, y^2, z^2, x y, x z, y z}
(* {True, True, False, False, False, False} *)

If you really want all of the expressions in that list above to match, I would do something like

MatchQ[#, a_ b_ | a_^2] & /@ {x^2, y^2, z^2, x y, x z, y z}
(* {True, True, True, True, True, True} *)
  • 1
    $\begingroup$ If the user wants to capture only x and y, a little work is required: MatchQ[#, a_ (b_ /; MatchQ[b, x | y]) | a_^2 /; MatchQ[a, x | y]] &. $\endgroup$
    – rcollyer
    Jun 13, 2016 at 21:06
  • $\begingroup$ @rcollyer. Or MatchQ[#, a_ b_ | a_^2 /; And[Or[a == x, a == y], Or[b == x, b == y]]] &. $\endgroup$
    – march
    Jun 13, 2016 at 21:07

I guess what you want is to create a function that can match something like $x x$ or $x y$ in a simple way.

So, here's my answer and hope this can help you:

f = Function[{t, l}, With[{pat = Alternatives @@ l},MatchQ[Unevaluated@t, HoldPattern[pat pat]]],HoldFirst];
f[x x, {x, y, z}]
f[x z, {x, y, z}]

Also, I think you would love to use something like Map:

f[#, {x, y, z}] & /@ (Unevaluated /@Unevaluated[{x x, x y, y y, z y}])

Can this help?


Thank you everyone!

Eventually I found the solution at Dropping Higher Order Terms in symbolic evaluation.

The one using

Normal[Series[expr /. Thread[vars -> t*vars], {t, 0, 10}]] /. t -> 1

My final code (for getting the components of the Riemann tensor of a certain weak gravitational field) became.

X = {t, x, y, w};
ds2 = -(1 + 2 \[Phi][t, x, y, w]) dt^2 + (1 - 2 \[Phi][t, x, y, w]) (dx^2 + dy^2 + dw^2);
Gdd = Metric[ds2, X];
termPattern = Join[{\[Phi][t, x, y, w]}, Flatten[D[\[Phi][t, x, y, w], {{t, x, y, w}, 1}]], Flatten[D[\[Phi][t, x, y, w], {{t, x, y, w}, 2}]]];
Result = Raise[Riemann[Gdd, X], 1, Gdd];
ResultFirstOrder = Normal[Series[Result /. Thread[termPattern -> i*termPattern], {i, 0, 1}]] /. {i -> 1, \[Phi]_[t, x, y, w] -> \[Phi]}

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.