5
$\begingroup$

I need to match a products with exactly one factor F, an arbitrary number of factors of head A, and possibly additional inert factors. I'm having trouble writing one pattern that can capture all the following cases.

I tried the following rule (the c term is there for show)

rule1 = Times[ayes___A, F] :> func[Times[ayes], F]; c + F /. rule1 c + A[x] F /. rule1 c + A[x] A[y] F /. rule1 c + d A[x] A[y] F /. rule1 
c + F (*desired: c + func[1,F] *) c + func[A[x], F] (*correct*) c + func[A[x] A[y], F] (*correct*) c + d func[A[x] A[y], F] (*correct*) 

The first expression failed to properly match, because it doesn't have head Times. Then I tried a second rule with Optional:

rule2 = rule2 = Times[Optional[ayes__A], F] :> func[Times[ayes], F]; (*Input same as above but with /. rule2*) 
c + func[1,F] (*correct*) c + func[A[x], F] (*correct*) c + func[A[x] A[y], F] (*correct*) c + d A[x] A[y] func[1, F] (*desired: c + d func[A[x] A[y], F] *) 

This time the fourth expression failed to match because of the extra factor. So now I try a third rule to accommodate that extra factor:

rule3 = Times[extra_. Optional[ayes__A], F] :> extra*func[Times[ayes], F] (*Input same as above but with /. rule3*) 
c + func[1,F] (*correct*) c + func[A[x], F] (*correct*) c + A[y] func[A[x], F] (*desired: c + func[A[x] A[y], F]*) c + d A[y] func[A[x], F] (*desired: c + d func[A[x] A[y], F] *) 

Now the pattern matcher got confused probably because of all the optional arguments.

Is there a single pattern that can match all these cases? Since I'm working with potentially large expressions, I would also prefer to avoid using pattern tests (Conditional) for performance reasons.

$\endgroup$
3
  • 1
    $\begingroup$ Does this get them all? Times[a_. ayes__A, F] | a_. F :> a func[Times[ayes], F]? $\endgroup$ Commented Mar 20, 2016 at 22:23
  • $\begingroup$ @march It doesn't get the third expression properly, c + A[y] func[A[x], F] $\endgroup$ Commented Mar 20, 2016 at 22:56
  • $\begingroup$ Right. Missed that one. I still think Alternatives is the way to go, although I'm not sure if it has the same performance hit as using pattern tests. For instance, rule1 = Times[ayes__A, F] | Times[a_ ayes__A, F] | a_. F :> a func[Times[ayes], F];. $\endgroup$ Commented Mar 20, 2016 at 22:59

1 Answer 1

2
$\begingroup$

ReplaceAll can use a list of rules.

Here the first rule in the list addresses Times and F. The second rule (which is only invoked if the first rule is not used) addresses Plus and F.

rule = {Times[F, extra_., ayes__A] -> extra func[Times[ayes], F], c_ + F -> c + func[1, F]} 

Now

c + F /. rule c + A[x] F /. rule c + A[x] A[y] F /. rule c + d A[x] A[y] F /. rule 

produces

c + func[1, F] c + func[A[x], F] c + A[x] func[A[y], F] c + d func[A[x], A[y], F] 
$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.