Group Abstract Group Abstract

Message Boards Message Boards

0
|
412 Views
|
5 Replies
|
8 Total Likes
View groups...
Share
Share this post:

How to reproduce the behavior of MemberQ[{a, b}, a] using MatchQ instead

Posted 1 month ago

I have been thinking how MemberQ is a sort of special case of MatchQ. MemberQ assumes a list, rather than simply a pattern, as MatchQ does -- as its second argument. For example:

MemberQ[{a, b}, a]
MatchQ[{a, b}, {___, a, ___}]
MatchQ[{a, b}, {___, ___, a, ___, ___}]
MatchQ[{a, b}, List[___, a, ___]]
MatchQ[{a, b}, List[___, ___, a, ___, ___]]

(* OUTPUT: *)
(* True *)
(* True *)
(* True *)
(* True *)
(* True *)

Is there any way to write the pattern in MatchQ without explicitly specifying the List? I'm thinking of something like the following: MatchQ[{a, b}, ___ ~~ a ~~ ___]

...but that's incorrect syntax (and returns False) because the use of ~~ implies a StringExpression, and {a, b} is clearly not a StringExpression. So, how can I write a pattern representing "any subexpression containing the symbol a anywhere"?

I could accomplish this using the resource function ContainsQ:

ResourceFunction["ContainsQ"][{a, b}, a]

(* OUTPUT: *)
(* True *)

But what is the built-in way to do this?

Looking at the source notebook for the resource function ContainsQ, I see that the definition of ContainsQ is simply:

ContainsQ[args___] := (Needs["GeneralUtilities`"]; GeneralUtilities`ContainsQ[args])
POSTED BY: Andrew D
5 Replies

Is _[___, a, ___]_ a regex-like syntax?

It's a good idea to examine the FullForm of things when trying to figure out pattern-matching:

FullForm[ _[___,a,___]_ ]
(*  Times[Blank[], Blank[][BlankNullSequence[],a,BlankNullSequence[]]]  *)

Since Blank[] and _ are the same, and BlankNullSequence[] and ___ are the same, the form can be written as the following, using * to indicate the head Times:

_ * _[___, a, ___]

It is probably clear that _[___, a, ___] matches any expression with any head and a as one of its arguments, like Power[x, a] in the test expression Times[Power[x, a], Power[y, b], Power[z, c]]. Probably less clear are the implications for pattern-matching because Times has the attributes Flat and Orderless. The test expression Times[Power[x, a], Power[y, b], Power[z, c]] is equivalent to

Times[ Times[Power[y, b], Power[z, c]], Power[x, a] ]

And therefore, the blank _ before the Times symbol * can match Times[Power[y, b], Power[z, c]] while the _[___, a, ___] after the Times symbol matches the other factor Power[x, a]. This is why one gets

MatchQ[Times[Power[x, a], Power[y, b], Power[z, c]], _[___, a, ___]_]
(*  True  *)
POSTED BY: Michael Rogers

Is there a way to write a pattern representing "any expression with a subexpression a anywhere" for use as the second argument to MatchQ?

This is a different question to the one about MemberQ equivalent codes.

I think what you want is ! FreeQ[expr, a]. It will return True if expr contains a anywhere. It is commonly used to detect the presence or absence of a pattern in an expression. There is also a useful option, FreeQ[expr, a, Heads -> False], which ignores whether the heads contain a and checks only the arguments.

POSTED BY: Michael Rogers
Posted 1 month ago

I'm sorry, but I'm very confused. You said,

MemberQ assumes a list, rather than simply a pattern ... as its second argument.

But then you give the example of MemberQ[{a, b}, a]. So, clearly you didn't write what you meant.

Then you ask for a pattern that works with MatchQ, but later you say that ContainsQ does what you want (but isn't built-in).

So, do you really need MatchQ? Why can't you use MemberQ just like ContainsQ? Maybe you should tell us more about the problem you're trying to solve rather than pre-constraining the discussion to specific symbols that you've already tried.

POSTED BY: Eric Rimbey
Posted 1 month ago

Sorry. I made multiple typos in the first paragraph of my original question. I should have said:

  • MemberQ takes a list as its first argument. (Actually, this is not true. As Michael Rogers points out elsewhere on this page, MemberQ can take any head as its first argument, not just List.)
  • MatchQ takes an expression as its first argument.

I'm trying to understand how to write a pattern representing the notion "any subexpression containing the symbol a anywhere."

If I have a string, I can write a string pattern (StringExpression) representing the notion "a string containing the character a" simply by writing ___ ~~ "a" ~~ ___. This string pattern can be used as the second argument to StringMatchQ:

StringMatchQ["abc", ___ ~~ "a" ~~ ___]
StringMatchQ["baac", ___ ~~ "a" ~~ ___]
StringMatchQ["xyz", ___ ~~ "a" ~~ ___]

(* OUTPUT: *)
(* True *)
(* True *)
(* False *)

But what is the analogue for the symbol a in a (general) pattern, rather than the character "a" in a string pattern? The following is obviously invalid syntax:

MatchQ[Times[Power[x, a], Power[y, b], Power[z, c]], ___ ~~ a ~~ ___]

(* OUTPUT: *)
(* False *)

Is there a way to write a pattern representing "any expression with a subexpression a anywhere" for use as the second argument to MatchQ? That's my question. Thanks to Michael Rogers's suggestion elsewhere on this page, it turns out that this does the trick:

MatchQ[Times[Power[x, a], Power[y, b], Power[z, c]], _[___, a, ___]_]

(* OUTPUT: *)
(* True *)

But I don't think I understand why. Is _[___, a, ___]_ a regex-like syntax?

Alternatively, I can obtain the result I want more simply using the resource function ContainsQ:

ResourceFunction["ContainsQ"][Times[Power[x, a], Power[y, b], Power[z, c]], a]

(* OUTPUT: *)
(* True *)

I can also obtain the result I want using MemberQ, though not directly (as far as I can tell) because a is in the exponent:

MemberQ[Times[Power[x, a], Power[y, b], Power[z, c]], a]
MemberQ[Times[Power[x, a], Power[y, b], Power[z, c]], Power[x, a]]

(* OUTPUT: *)
(* False *)
(* True *)

My observation is, ContainsQ is quite useful! So my follow-up question is, why didn't (or doesn't) Wolfram include ContainsQ as a built-in function? The answer is probably "because you can just use MatchQ in the way Michael Rogers suggested elsewhere on this page":

MatchQ[Times[Power[x, a], Power[y, b], Power[z, c]], _[___, a, ___]_]

(* OUTPUT: *)
(* True *)
POSTED BY: Andrew D

Note MemberQ[a + b + c, a] returns True, so any head is allowed.

I think you want MatchQ[list, {___, a, ___}]. Or more generally, MatchQ[expr, _[___, a, ___]].

POSTED BY: Michael Rogers
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard