6
$\begingroup$

I'm looking for a nice way to split an expression into a list of the terms (i.e. the addends).

The desired behavior in:

terms[a^2 + a^-2 + c]  
(* Out: {a^2, a^-2, c} *)
terms[a*b*c]
(* Out: {a*b*c} *)

I've tried a few solutions. MonomialList doesn't work if the expression is not a polynomial. I've also tried

Level[a + b + c, 1]
(* Out: {a, b, c} *)

But the problem is it breaks down for monomials.

Level[a, 1]
(* Out: {} *)
Level[a*b*c, 1]
(* Out: {a, b, c} *)

The desired output would be {a} and {a b c} respectively.

Thank you in advance!

$\endgroup$
2
  • $\begingroup$ terms[a*b*c] but terms here are a and b and c. Unless you are using your own definition of what a term is. So you can use List @@ expr to obtain the terms. expr = a^2 + a^-2 + c; List @@ expr gives {1/a^2, a^2, c} and expr = a*b*c; List @@ expr gives {a, b, c} etc.. $\endgroup$
    – Nasser
    Feb 15 '20 at 22:12
  • $\begingroup$ @Nasser Thank you for your reply. To clarify, I am using "term" to mean addend. I am finding that the ` List @@ expr ` similarly does not handle monomials correctly. Namely expr = a; List @@ expr returns just a rather than {a}. $\endgroup$
    – mwalth
    Feb 15 '20 at 22:18
7
$\begingroup$
ClearAll[terms]
SetAttributes[terms, HoldAll]
terms[Plus[a__]] := {a}
terms[a_?AtomQ] := {a}
terms[a_] := a

Examples:

ClearAll[a, b, c, d]

terms[a]

{a}

terms[a + b + c]

{a, b, c}

terms[a b c]

a b c

terms[a^2 + a^-2 + c]

{a^2, 1/a^2, c}

terms[a b c + 3 Sin[c + d] + Log@d]

{a b c, 3 Sin[c + d], Log[d]}

$\endgroup$
5
  • 2
    $\begingroup$ This works perfectly! I appreciate you putting in the effort. $\endgroup$
    – mwalth
    Feb 16 '20 at 2:21
  • $\begingroup$ @mwalth, you are welcome. And welcome to mma.se. $\endgroup$
    – kglr
    Feb 16 '20 at 2:28
  • $\begingroup$ As always: cool answer from you! $\endgroup$
    – mgamer
    Feb 17 '20 at 9:52
  • $\begingroup$ But when I write u=a+b and terms[u] your function does not work. Do you know how to generalize? $\endgroup$
    – yarchik
    Jun 19 '20 at 13:19
  • 1
    $\begingroup$ @yarchik, you can use terms[Evaluate@u] ? $\endgroup$
    – kglr
    Jun 19 '20 at 20:44
4
$\begingroup$

For the examples you mentioned, the following simple replacement works:

a^2 + a^-2 + c /. Plus -> List

(* Out: {1/a^2, a^2, c} *)

Note that the ordering is not retained, but then you probably shouldn't depend on the order of monomials anyway because MMA might rewrite your expression on its own to conform to its "canonical" format (e.g. evaluating b - a returns -a + b).

Similarly,

a*b*c /. Plus -> List     (* Out: a*b*c *)
a /. Plus -> List         (* Out: a     *)
$\endgroup$
1
  • $\begingroup$ Thank you for your response! This seems to work well for expressions with multiple expressions, but I'm finding that abc /. Plus->List returns abc whereas I would hope for it to return the singleton list {abc}. Do you know how to modify so that it returns a list regardless of the number of terms in the input? $\endgroup$
    – mwalth
    Feb 16 '20 at 2:33
2
$\begingroup$

No sure whether I got your point, but you can do something like (o.k. broth-force attack ;-) ):

    makeList[term_] := 
 ToExpression /@ StringSplit[ToString[term, InputForm], "+"
   ]

then

temp = a^2 + a^-2 + c

and

makeList@temp

yields:

{1/a^2, a^2, c}
$\endgroup$
3
  • 1
    $\begingroup$ Thank you for the response. This was a route I thought about going also. I realize I didn't specify this in the question, but I also need it to split terms that have a minus "-" in addition to a plus "+". Do you know if this is possible with your method? $\endgroup$
    – mwalth
    Feb 16 '20 at 2:23
  • 1
    $\begingroup$ You can use StringSplit[term,{"+","-"}] this should work $\endgroup$
    – mgamer
    Feb 16 '20 at 8:23
  • $\begingroup$ Very good, thank you! $\endgroup$
    – mwalth
    Feb 16 '20 at 13:17

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.