# Is it possible to match a sequence with multiple heads without using Condition

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?

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.

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.