4
$\begingroup$

Suppose I have:

expr = Times[2, a[x,r], a[y,1], c[z,0,0], d[w,m]];

If I want to match a sequence of expressions with the same head a, I would use a PatternSequence like this: __a, e.g.:

 expr /. Times[rest___, subExpr__a] :> myfunc[Times[subExpr]]
myfunc[a[x, r] a[y, 1]]

But what if I want to match a sequence of expressions with multiple heads a or d? The only way I know how to do this is by using Condition:

expr /. Times[Longest[rest___], subExpr__] /; FreeQ[Times[rest], _a | _d] :> myfunc[Times[subExpr]]
myfunc[a[x, r] a[y, 1] d[w, m]]

My expressions are very long and complicated and ideally, I'd like to avoid having to use Condition which requires calls to the Kernel. Is there a way to accomplish my task purely with the pattern-matcher?

$\endgroup$
5
$\begingroup$

Instead of using BlankSequence, use PatternSequence:

expr /. Times[rest___, subExpr : PatternSequence[___a, ___d]] :> myfunc[Times[subExpr]]
myfunc[a[x, r] a[y, 1] d[w, m]]

The orderlessness of the pattern sequence is ensured by the Orderless attribute of Times.

$\endgroup$
3
$\begingroup$

Instead of pattern-matching the expressions you want to keep, you could also remove the ones you do not want to keep:

myfunc[Replace[expr,x_ /; Not@MemberQ[{a, d}, Head@x] -> Sequence[], {1}]]

This approach should be faster than using pattern matching using multiple blanks. It also works with other expression heads than Times.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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