1
$\begingroup$

I am trying to define a replacement rule for an arbitrary sum of terms in an equation, that returns the x[i] terms along with their coefficients. For example,

eqns = {0 == x[1] + y[2], 
         0 == 1 - 8 x[5], 
         0 == 1 + 2 x[3] + 4 y[2] + 3 x[1]}

Here's the pattern I tried using

patt = (0 == Plus[Optional[a__], Optional[b_]x[c_], Optional[d__]]])

eqns /. pattern :> b * x[c]

but this outputs

{x[1], - 8 x[5], 3 x[1]}

the output I want is something like

{x[1], - 8 x[5], {2 x[3], 3 x[1]}}

For some reason it's defaulting to the 3x[1] replacement instead of the 2x[3] replacement. Is there a way to design a replacement rule that spits out all matches in the expression?

( I would prefer it if it could be written in in the form

eqns /. pattern :> something

)

$\endgroup$
3
$\begingroup$

Your replacement returns only one term because only one term is specified in the pattern. Compare

x[1] + x[2] /. Plus[Optional[a__], Optional[b_] x[c_], Optional[d__]] :> x[c]
(*x[1]*)

and

x[1] + x[2] /. Plus[Optional[a__], Optional[b_] x[c_], Optional[b1_] x[c1_],   Optional[d__]] :> {b x[c], b1 x[c1]}
(*{x[1], x[2]}*)

Of course, such an approach will not work when you don't know how many terms there will be in the expression. For such cases, there is Repeated pattern that stands for a sequence of any number of terms:

eqns /. (0 == Plus[seq : Repeated[_. _x], ___] :> {seq})
(*{{x[1]}, {-8 x[5]}, {3 x[1], 2 x[3]}}*)

I also strongly recommend not using patterns Optional[__] anywhere. __ stands for one or more expressions, which means that MMA will try to populate this patterns at least by one expression first and only if it fails, MMA will use Default. An example:

x[1] + x[2] /. Plus[Optional[a__], Longest[seq : Repeated[_. _x]],    Optional[d__]] :> {{seq}, a, d}
(*{{x[1]}, x[2], 0}*)

Note that even using Longest does not help here. Further, there is no need to use Optional at all in your example because your can just use BlankNullSequence, which stands for zero or more expressions. Finally, Plus is Orderless, which means that you don't need to care about order of the terms inside Plus.

x[1] + x[2] + x[3] /. Plus[x[1], x[3], ___] -> True
(*True*)

In fact, this is the reason why Repeated worked in the example above, because Repeated stands for a sequence of expressions which come one after another.

$\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.