5
$\begingroup$

Here is a sample expression that contains a bunch of f and some other stuff:

expr = a f[x] + b f[y] + 2 c f[z] + f[a] + Cos[y] + 3 f[y] + Sqrt[x]

and I would like to apply function modify1 to the part of the expression containing f[x] f[y] and f[z] exclusively (not f[a]), and modify2 to the rest. The pattern that matches is: Plus[rest___, Times[_., f[x | y | z]] ..] and I am using it like so:

expr /. Plus[rest___, Times[_., f[x | y | z]] ..] :> modify1[Plus[(*???*)]] + modify2[Plus[rest]]
modify1[] + modify2[Sqrt[x] + Cos[y] + f[a]]

What I want is:

modify1[a f[x] + b f[y] + 2 c f[z] + 3 f[y]] + modify2[Sqrt[x] + Cos[y] + f[a]]

To make this work, I need to name the part of the pattern that has all the f[x], f[y], f[z] so I can apply the modify1 function to it. But if I try to insert a name to the pattern like so:

expr /. Plus[rest___, (name: Times[_., f[x | y | z]] ..)] :> modify1[Plus[name]] + modify2[Plus[rest]]

The pattern matches incorrectly:

modify1[a f[x]] + modify2[Sqrt[x] + Cos[y] + f[a] + 3 f[y] + b f[y] + 2 c f[z]]

How do I name Times[_., f[x | y | z]] .. inside of Plus so that the pattern correctly matches and can be subsequently manipulated? Note that the list of arguments x y z is variable, so I prefer to avoid a brute force solution.

$\endgroup$

2 Answers 2

4
$\begingroup$

You could use

modify1[Plus @@ #] + modify2[Plus @@ Complement[List @@ expr, #]] &[Cases[expr, _Times]]

modify1[a f[x] + 3 f[y] + b f[y] + 2 c f[z]] + modify2[Sqrt[x] + Cos[y] + f[a]]

What should happen to a "single" f[x|y|z] not being part of Times?

Depending on what you want you could modify the argument like

Cases[expr, Times[__, f[x | y | z]] | f[x | y | z]]
$\endgroup$
2
  • $\begingroup$ This is great. It seems like Cases[expr, _. f[a|b|c]] works, too. Any reason you can think of why it wouldn't work? $\endgroup$
    – QuantumDot
    Commented Jan 2, 2016 at 14:27
  • $\begingroup$ The default level specification for Cases is 1. You may have to use Infinity or something higher. $\endgroup$ Commented Jan 2, 2016 at 15:29
1
$\begingroup$

The expression is slightly modified to include the cases where f[x] may not have a multiplier and f[a] may have a multiplier or be enclosed in a function.

expr = a f[x] + b f[y] + 2 c f[z] + f[a] +
             Cos[y] + f[y] + Sqrt[x] + Cos[f[a]]

It is desired to capture all elements that include f[a] or f[b].

Cases[expr, f[a | b] | (x_ /; MemberQ[x, f[a | b]])]
(* {Cos[f[a]], f[a]} *)

This will be used as input to Eldo's fine answer where the expression is converted to a list and the Complement is taken. However since this returns the elements containing f[a] the output will be applied to modify2 and the Complement to modify1.

modify1[Plus @@ Complement[List @@ expr, #]] +
   modify2[Plus @@ #] &[Cases[expr, f[a | b] | (x_ /; MemberQ[x, f[a | b]])]]

returns

Mathematica graphics

$\endgroup$
2
  • $\begingroup$ Very nice. In a comment to Eldo, I mentioned using Cases[expr, _. f[a|b|c]] to capture the possibility f doesn't have a multiplier. What do you think? $\endgroup$
    – QuantumDot
    Commented Jan 2, 2016 at 17:42
  • $\begingroup$ That handles multipliers on f[a] fine. It doesn't handle the case where f[a] is an argument to a function. If your data only uses multipliers Cases[expr, _. f[a|b|c]] should work fine. $\endgroup$ Commented Jan 2, 2016 at 19:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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