Seemingly a relatively simple problem, I can't seem to find a solution...
I want to build a pattern that will match any symbol whose name starts with V, and is elevated at any power. Something on the line of:
MatchQ[#1, (V1 | V2 | V3)^_.] & /@ {V1, V1^2, V2}
That returns true for each of the entries. I haven't found a way to put constrains on the symbol name, if not by using SymbolName[] and working with string patterns:
MatchQ[#1, (_)?(StringMatchQ[SymbolName[#1], "V" ~~ __] &)^_.] & /@ {V1, V1^2, V2}
However, it doesn't look exactly beautiful... (only to me?) :-) Is there a more compact and elegant way of putting constraints on a symbol name? I'm feeling like I'm totally missing a very obvious function that would do that...
Answer
I believe that if you want to match a Symbol by its constituent characters that you do need to use string patterns, therefore your solution is reasonable. I recommend a variation:
p2 = s_Symbol^_. /; StringMatchQ[SymbolName[s], "V*"]
s_Symbol makes sure that the expression that is passed to SymbolName is actually a Symbol. I also find it somewhat more readable. Test:
MatchQ[p2] /@ {V1, V1^2, V2, x^2, y} (* v10 operator form syntax *)
{True, True, True, False, False}
The use of Condition rather than PatternTest makes it easier if you may be working with held expressions and need to add Unevaluated:
p3 = s_Symbol^_. /; StringMatchQ[SymbolName[Unevaluated@s], "V*"]
This allows:
V1 = "Fail!";
Cases[Hold[V1, V1^2, V2, x^2, y], x : p2 :> Hold[x]]
V1 =.;
{Hold[V1], Hold[V1^2], Hold[V2]}
To make the code a bit prettier consider an abstraction such as:
symPat = s_Symbol /; StringMatchQ[SymbolName[Unevaluated@s], #] &;
Then simply:
Cases[{V1, V1^2, V2, x^2, y}, symPat["V*"]^_.]
{V1, V1^2, V2}
Comments
Post a Comment