# Using Cases and when to make input a list or not

I am back learning pattern matching in Mathematica, which I am not good at.

An input is a mathematica expression, and I need to simply get a list of all the sub-expressions inside this expression of the pattern (any0_. Exp[any1_. c + any2_.]) anywhere in the expression.

c above is the literal symbol. All others are patterns.

For example, the above pattern will match $e^{c +x}$ or $4 e^{5 c+ x}$ and so on. So I tried it and it works, except when the input expression contains a single Exp[...]

case 1, works

ClearAll[x,y,c]
expr=x y +4 Exp[c + y]+5 Sin[x]+Exp[c + x]
Cases[expr,(any0_. Exp[any1_. c + any2_.])]


case 2, works

expr=x y +4 Exp[c + y]+5 Sin[x]
Cases[expr,(any0_. Exp[any1_. c + any2_.])]


case 3, do not work

expr=4 Exp[c + y]
Cases[expr,(any0_. Exp[any1_. c + any2_.])]


the 4 was dropped out in the above. And when there is a single Exp it does not work at all

case 4, do not work

expr=Exp[c + y]
Cases[expr,(any0_. Exp[any1_. c + any2_.])]


I can handle these last two special cases by forcing the input to be a list

expr=Exp[c + y]
Cases[{expr},(any0_. Exp[any1_. c + any2_.])]


But if I do the above, then the first two cases now fail. So I changed the test to be as follows

If[Head[expr] === Plus,
Cases[expr, (any0_. Exp[any1_. c + any2_.])]
,
Cases[{expr}, (any0_. Exp[any1_. c + any2_.])]
]


And now the above works for all of 4 cases. (But I am not sure if it will fail for some cases I have not thought about as I only check for Plus head)

My question is, is the above a correct way to do all of this, or is there a better and canonical way to handle this in Mathematica?

Update: Thanks to all the answers. But I also need it to work for division. As in this new case

case 5

 expr = Exp[c + x]/(3 + Exp[3*c + x]);


So in the above, it should find Exp[c + x] and Exp[3*c + x] separately. The whole idea, is that I want to rewrite any subexpression Exp[any1_*c + any2_] as c*Exp[any2]

I did say in the original question above anywhere in the expression but I did not put the above case in there and I was just now testing the answers given and noticed this problem.

• Use the level specs to include level 0 : Cases[expr, (any0_. Exp[any1_. c + any2_.]), {0, Infinity}]? – kglr Jul 19 '17 at 22:07
• @kglr But your method will now return 2 hits for this: 4 Exp[c + y], it returned {E^(c+y),4 E^(c+y)} and I only wanted 4 E^(c+y) ? screen shot !Mathematica graphics – Nasser Jul 19 '17 at 22:10
• Cases[expr, (any0_. Exp[any1_. c + any2_.]), {0}] gives a single hit. – kglr Jul 19 '17 at 22:13
• @kglr Sure, now it gives single hit on this case, but for case 1 it now returns empty list ! expr = x y + 4 Exp[c + y] + 5 Sin[x]; Cases[expr, (any0_. Exp[any1_. c + any2_.]), {0}] gives empty list. !Mathematica graphics This is not as easy as it looks :) I need a method that works for all cases. – Nasser Jul 19 '17 at 22:15
• Nasser, it does give an empty list as it should. For "a method that works for all cases", you need to decide and specify the levels you you are looking for a match: 4 Exp[c + y] will have two matches for levelspec {0,1}and one for levelspec 0. With your If[...] approach you are just adding one more level to input expr (hence default levelspec 1 kicks in). In general the pattern in the second argument, in addition to being inside an expression with any Head, can be at arbitrary depth (consider y + foo[bar[4 Exp[c=y]] for example). – kglr Jul 19 '17 at 22:33

Instead of Cases, you can use ReplaceAll. ReplaceAll will not search inside of a part of the expression that it already replaced, unlike Cases which searches at every level specified. So:

getPatterns[expr_, pat_] := Last @ Reap[
expr /. a:pat :> Sow[a],
_,
Sequence@@#2&
]


expr1=x y+4 Exp[c+y]+5 Sin[x]+Exp[c+x];
expr2=x y+4 Exp[c+y]+5 Sin[x];
expr3=4 Exp[c+y];
expr4=Exp[c+y];

getPatterns[#, _. Exp[_. c+_.]]& /@ {expr1, expr2, expr3, expr4}


{{E^(c + x), 4 E^(c + y)}, {4 E^(c + y)}, {4 E^(c + y)}, {E^(c + y)}}

• Thanks for the answer. I just found the above does not work for division? Here is an example: expr = Exp[c + x]/(3 + Exp[3*c + x]) getPatterns[expr, (_. Exp[_. c + _.])] and this does not find Exp[c + x] and Exp[3*c + x], but it returns the whole expression back. Is it hard to make your function find these patterns also in there is a division? I did not put this example in my question, but I said anywhere in the expression. :) and I was now just testing this answer. I should add this case now. Thanks. – Nasser Jul 21 '17 at 5:21
• The whole expression does match the pattern, it is 1/(3 + Exp[3 c+x]) times Exp[c+x]. Perhaps something like getPatterns[expr, x_. Exp[_. c + _.] /; FreeQ[x, E]] or getPatterns[expr, _Integer Exp[_. c + _.]]? – Carl Woll Jul 21 '17 at 5:28
• Thanks, getPatterns[expr, x_. Exp[_. c + _.] /; FreeQ[x, E]] seems to work! Will test more now. Pattern matching is too hard. – Nasser Jul 21 '17 at 5:31

Your problem seems to be basically a level specification problem. We can see what's going on by looking a much simpler case.

Cases[Exp[c + y], Exp[c + _]]


{}

Cases will accept expressions with any head, but it normally only looks at the elements at level 1 of the expression. Therefore, in this example, it only sees the argument c + y, which does not match the pattern, so it returns an empty list.

There are two work-arrounds.

The obvious one

Cases[{Exp[c + y]}, Exp[c + _]]


(now Exp[c + y] is at level 1) and the less obvious one

Cases[Exp[c + y], Exp[c + _], {0}]


(now Cases looks at level 0). They both return

{E^(c + y)}

Update: Maybe something like this

ClearAll[caseS]
caseS = Module[{i = 0, res = {}}, While[i < Depth[#] &&
(res = Cases[{#}, (any0_. Exp[any1_. c + any2_.]), i++])  === {}]; res] &;

expr1 = x y+ 4 Exp[c + y]+ 5 Sin[x] + Exp[c + x];
expr2 = x y+ 4 Exp[c + y]+ 5 Sin[x];
expr3 = 4 Exp[c + y];
expr4 = Exp[c + y];

caseS /@ {expr1, expr2, expr3, expr4}


{{E^(c + x), 4 E^(c + y)}, {4 E^(c + y)}, {4 E^(c + y)}, {E^(c + y)}}

caseS /@ {foo[expr1], {expr2}, {{{bar @@ {{expr3}}}}}, {{{expr4}}}}


{{E^(c + x), 4 E^(c + y)}, {4 E^(c + y)}, {4 E^(c + y)}, {E^(c + y)}}

expr = 4 Exp[c + y]
Cases[expr, (any0_.  Exp[any1_. c + any2_.]), {0, Infinity}]


{E^(c + y), 4 E^(c + y)}

Or get the matches in level 0 only:

Cases[expr, (any0_.  Exp[any1_. c + any2_.]), {0}]


{4 E^(c + y)}

expr = Exp[c + y]
Cases[expr, (any0_. Exp[any1_. c + any2_.]), {0, Infinity}]]


{E^(c + y)}

• The default value for levelspec in Cases is {1}.

And 4 Exp[c + y] has two elements Level 1

Level[4 Exp[c + y], 1]


{4, E^(c + y)}

Only the second matches the pattern and is returned by Cases with default levelspec.

Similarly,

Level[Exp[c + y], 1]


{E, c + y}

none of which matches the pattern specified.

You need to include level 0 to force pattern matching to include the whole expression.

• Thanks, but please see comment above. This returns 2 hits for 4 Exp[c + y] when I only expect one !Mathematica graphics – Nasser Jul 19 '17 at 22:13
• Using {0} does not work on case 1 !Mathematica graphics and using {0, Infinity} gives two hits for 4 Exp[c + y] !Mathematica graphics I am looking for one method that will work for all cases. But thanks for the input. – Nasser Jul 19 '17 at 22:31
• +1 thanks for information about level. But I am hoping for general method that works for all cases. Will keep trying :) – Nasser Jul 19 '17 at 22:57