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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.