开发者

Split expression into collection of terms

I have a long expression that I would like to split into a collection of terms. For example say I have:

a + b - c + d + 4*e - 3*f

I want to split the expressi开发者_开发问答on by addition/subtraction into:

{a, b, -c, d, 4*e, -3*f}

My motivation for this is that I want to deal with the original expression term by term. Is this possible?

Edit: The examples given are VERY simplistic compared to what I'm actually dealing with in Mathematica, it's just that I'm not sure how to write Math around here.


To split the expression, you need to use Level. Level gives you a list of subexpressions and you can specify the level at which you want the subexpressions returned. In this case, you need levelspec 1.

In[1]:= expr = a + b - c + d + 4 e - 3 f;
In[2]:= Level[expr, 1]

Out[2]= {a, b, -c, d, 4 e, -3 f}

An example with a slightly more complicated expression:

In[3]:= expr2 = a^2 + 5 bc/ef - Sqrt[g - h] - Cos[i]/Sin[j + k];
In[4]:= Level[expr2, 1]

Out[4]= {a^2, (5 bc)/ef, -Sqrt[g - h], -Cos[i] Csc[j + k]}


Since no one else has mentioned it, equivalent to Yoda's Level[expr, 1] construction is to use Apply to replace the head of an expression with List:

In[1]:= expr = a + b - c + d + 4 e - 3 f;

In[2]:= List @@ expr
        Level[expr, 1] == %

Out[2]= {a, b, -c, d, 4 e, -3 f}
Out[3]= True


In[4]:= expr2 = a^2 + 5 bc/ef - Sqrt[g - h] - Cos[i]/Sin[j + k];

In[5]:= List @@ expr2
        Level[expr2, 1] == %

Out[5]= {a^2, (5 bc)/ef, -Sqrt[g - h], -Cos[i] Csc[j + k]}
Out[6]= True

The two methods do basically the same thing and have identical timings (using my version of a average timing function)

In[1]:= SetOptions[TimeAv, Method -> {"MinNum", 80000}, "BlockSize" -> 20000];

In[7]:= List @@ expr // TimeAv

Total wall time is 0.244517, total cpu time is 0.13 
and total time spent evaluating the expression is 0.13

The expression was evaluated 80000 times, in blocks of 20000 runs. This yields
a mean timing of 1.625*10^-6 with a blocked standard deviation of 2.16506*10^-7.

Out[7]= {1.625*10^-6, {a, b, -c, d, 4 e, -3 f}}

In[8]:= Level[expr, 1] // TimeAv

Total wall time is 0.336927, total cpu time is 0.16 
and total time spent evaluating the expression is 0.16

The expression was evaluated 80000 times, in blocks of 20000 runs. This yields 
a mean timing of 2.*10^-6 with a blocked standard deviation of 3.53553*10^-7.

Out[8]= {2.*10^-6, {a, b, -c, d, 4 e, -3 f}}


You might also be able to use MonomialList, if you expression is a polynomial:

In[56]:= MonomialList[a + b - c + d + 4*e - 3*f]

Out[56]= {a, b, -c, d, 4 e, -3 f}

(Doesn't work on non-polynomials, such as Yoda's expr2.)


You could also use Replace:

In[65]:= Replace[a + b - c + d + 4*e - 3*f, HoldPattern[Plus[a___]] :> {a}]

Out[65]= {a, b, -c, d, 4 e, -3 f}

You need to use HoldPattern (or some equivalent trick) to prevent Plus[a__] from evaluating to a__, which has the result of just wrapping the first argument in a list instead of creating a list of the arguments to Plus.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜