7
$\begingroup$

My apologies if this question has been asked before, but for the first 50 or so questions on coefficientlist, I couldn't find a similar topic.

If I've an expression which involves a variable with indices, and I want to collect its coefficients, how can it be achieved? For example, if my expression is

-27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] +  9 Subscript[u, 1, 3]
+ 36 Subscript[u, 2, 1] + 8 Subscript[u, 2, 2] - 12 Subscript[u, 2, 3]
- 9 Subscript[u, 3, 1] - 2 Subscript[u, 3, 2] + 3 Subscript[u, 3, 3]

then how can I collect {-27, -6, 9, 36, 8, -12, -9, -2, 3}. The expression can have several other terms, but always of the form of Subscript[u, i, j].

And, if all these terms have a common denominator, how that situation can be handled? So far I was simply taking the numerator part, but if I've to compare the coefficients of many expressions, considering the full expression will further help. In this situation, I found that the answers of Marius and Alexei work straight away.

For example, if my full expression looks like -((27 Subscript[u, 1, 1] + 6 Subscript[u, 1, 2] - 9 Subscript[u, 1, 3] - 36 Subscript[u, 2, 1] - 8 Subscript[u, 2, 2] + 12 Subscript[u, 2, 3] + 9 Subscript[u, 3, 1] + 2 Subscript[u, 3, 2] - 3 Subscript[u, 3, 3])/(16 hx))

then using Marius' and Alexei's suggestion, I get the expected answer {-(27/(16 hx)), -(3/(8 hx)), 9/(16 hx), 9/(4 hx), 1/( 2 hx), -(3/(4 hx)), -(9/(16 hx)), -(1/(8 hx)), 3/(16 hx)}.

$\endgroup$
6
  • 2
    $\begingroup$ This might be a bit hacky, but instead of using something like CoefficientList you can just extract them yourself: First /@ List @@ expression $\endgroup$ Mar 2, 2016 at 14:16
  • $\begingroup$ @MartinBüttner, I don't know about hacky, but that is a more intuitive method than those listed below. I feel really dumb but it took me forever to figure out why First /@ expression was giving 0 as the answer $\endgroup$
    – Jason B.
    Mar 2, 2016 at 15:20
  • $\begingroup$ @JasonB I guess I'll post it then. $\endgroup$ Mar 2, 2016 at 15:29
  • $\begingroup$ Thanks to all for your helpful answers, each of them teaching something new (to a newbie of Mathematica). The most elegant and simple answer I found for my purpose is from @MartinBüttner, which I'm selecting as the answer (I can only select one, but honestly appreciating everything). $\endgroup$
    – tomar.sk
    Mar 2, 2016 at 19:50
  • $\begingroup$ @Saku You might want to reconsider that. See kglr's comment on my answer. It doesn't work reliably if your coefficients could be 1. $\endgroup$ Mar 2, 2016 at 20:07

8 Answers 8

8
$\begingroup$

Since all terms have Subscript[something], we can use a pattern:

expr /. Plus -> List /. c_.*Subscript[__] :> c

{-27, -6, 9, 36, 8, -12, -9, -2, 3}

This assumes the expression has been Expanded so that the Head is indeed Plus. This will also give the coefficients in the same order as they appeared in the expression. If you also would like which coefficients belong with which coefficients, do:

expr /. Plus -> List /. c_.*Subscript[x__] :> {c, Subscript[x]}

{{-27, Subscript[u, 1, 1]}, {-6, Subscript[u, 1, 2]}, {9, Subscript[u, 1, 3]}, {36, Subscript[u, 2, 1]}, {8, Subscript[u, 2, 2]}, {-12, Subscript[u, 2, 3]}, {-9, Subscript[u, 3, 1]}, {-2, Subscript[u, 3, 2]}, {3, Subscript[u, 3, 3]}}

EDIT:

Explanation of replacement: First, all terms in expr are put in a list. Then, we replace all instances of expressions in that list that match the pattern c_.*Subscript[__] with just c. This pattern matches expressions where some expression c is multiplied by a Subscript expression with any arguments (at least one). The period in the pattern c_. lets us include the default value in multiplication, which is 1. If we had omitted it, the pattern would not match e.g. the last term in

3 Subscript[u,1,1] + Subscript[u,1,2]

because that term is not strictly "some expression multiplied with Subscript.

As for the ordering, yes, the ordering will be the same as that in expr as long as it is a "flat" sum, i.e. fully expanded.

$\endgroup$
3
  • $\begingroup$ Thanks. The second options can be certainly helpful in some situations, and I've noted it. But can you be kind enough to explain the whole idea after Plus -> List (in both the options)? Please note that I'm almost illiterate in Mathematica (coming from structured programming style). It will help to know how this works than just copying for one specific purpose. Also, though you already about it, as some other experts raised the question of ordering, will this construct maintain the order in all situations? $\endgroup$
    – tomar.sk
    Mar 3, 2016 at 9:30
  • $\begingroup$ Please see my edit :) $\endgroup$ Mar 3, 2016 at 12:35
  • $\begingroup$ Thanks a lot. This is indeed helpful, also for comparing your answer with that of Alexei (which might fail if the coefficient is 1). Given all the answers, and the flexibility of having a denominator, I'm selecting your answer as the final one. $\endgroup$
    – tomar.sk
    Mar 4, 2016 at 11:39
9
$\begingroup$

Yet another way to do this, using Coefficient

expr = -27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] + 
   9 Subscript[u, 1, 3] + 36 Subscript[u, 2, 1] + 
   8 Subscript[u, 2, 2] - 12 Subscript[u, 2, 3] - 
   9 Subscript[u, 3, 1] - 2 Subscript[u, 3, 2] + 
   3 Subscript[u, 3, 3];
Flatten@Array[Coefficient[expr, Subscript[u, #1, #2]] &, {3, 3}]
(* {-27, -6, 9, 36, 8, -12, -9, -2, 3} *)

Edit

Here's a way to get there using CoefficientList,

CoefficientList[expr, Variables[expr]] // Flatten // 
   DeleteDuplicates // Reverse // Most
(* {-27, -6, 9, 36, 8, -12, -9, -2, 3} *)
$\endgroup$
2
  • $\begingroup$ You could use Variables[expr] instead of the Table I guess. Anyway, nice one, I could not make sense of the array from CoefficientList so simply, +1. $\endgroup$ Mar 2, 2016 at 14:47
  • $\begingroup$ Thanks, I was unaware of Variables :-) $\endgroup$
    – Jason B.
    Mar 2, 2016 at 15:08
7
$\begingroup$

Turning my comment into an answer. If you know that this is exactly the form of the expression, you can just pick out the coefficients manually with First. It's important though that you first turn the sum into a list, because otherwise the coefficients will be summed up immediately:

First /@ List @@ expression

The List @@ replaces the head Plus with List. Then we simply pick out each coefficient with First, because Mathematica orders products with the coefficient first and the variable second.

Note that this doesn't work reliably if some of the terms have a coefficient of 1 (in that case, the variable itself would be returned). You could fix that with something like:

Replace[First /@ List @@ expression, n_ /; ! NumericQ@n -> 1, {1}]

But at that point it might be simpler to use one of the other answers.

Alternatively, as garej suggested in a comment, if you have a variable a that you know is unused, you could do:

First /@ List @@ Expand[a*expr] /. a -> 1
$\endgroup$
5
  • 1
    $\begingroup$ if some coefficients in expression are 1, this approach does not work. E.g. for exp2 used in my answer below, First /@ List @@ exp2 gives {u, -1, u, 36, 8}. $\endgroup$
    – kglr
    Mar 2, 2016 at 20:01
  • $\begingroup$ @kglr Oh, that's a very good point. $\endgroup$ Mar 2, 2016 at 20:04
  • $\begingroup$ @MartinBüttner, that is not as nice but you may use something like First /@ List @@ Expand[2*expr]/2 to avoid problem of 1. $\endgroup$
    – garej
    Mar 2, 2016 at 20:42
  • $\begingroup$ @garej Then what if you have a coefficient of 1/2? ;) $\endgroup$ Mar 2, 2016 at 20:42
  • $\begingroup$ @MartinBüttner, lol!! than may be one has to use First /@ List @@ Expand[a*expr] /. (a :> 1) $\endgroup$
    – garej
    Mar 2, 2016 at 20:46
4
$\begingroup$

Using @JasonB's expr, this also works:

expr[[#, 1]] & /@ Range[Length[expr]]
$\endgroup$
4
$\begingroup$

A few additional alternatives:

f1 = D[#, {Variables @ #}] &;
f2 = List @@ # /. Subscript -> (1 &) &;
f3 = # /. {Plus -> List, Subscript -> (1 &)} &;
f4 = Block[{Plus = List, Subscript = (1 &)}, #] &;
f5 = Coefficient[#, Variables @ #] &;
☺ = # /. u -> 1 & @@@ {##} & @@ # &;

Examples:

exp1 = -27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] + 
 9 Subscript[u, 1, 3] + 36 Subscript[u, 2, 1];

exp2 = Subscript[u, 1, 1] - Subscript[u, 1, 2] + Subscript[u, 1, 3] + 
   36 Subscript[u, 2, 1] ;

f1 /@ {exp1, exp2}

{{-27, -6, 9, 36}, {1, -1, 1, 36}}

Equal@@Through[{f1, f2, f3, f4, f5, ☺} @ exp1]

True

Through[{f1, f2, f3, f4, f5, ☺} @ exp2]

True

$\endgroup$
4
  • 1
    $\begingroup$ Wait, can we use emoji as variable names? This changes everything $\endgroup$
    – Jason B.
    Mar 2, 2016 at 19:35
  • $\begingroup$ @JasonB, yes we can ☺. $\endgroup$
    – kglr
    Mar 2, 2016 at 19:43
  • $\begingroup$ Thanks @kglr. The option f1 is a clever one using mathematical principle. Will the option f5 maintain the ordering, as some other experts have raised this issue? And, yes JasonB, I can confirm that emojis are also working. Hats off to kglr. $\endgroup$
    – tomar.sk
    Mar 3, 2016 at 9:36
  • $\begingroup$ @kglr, If I've a denominator in the expression, then the options f3, f4 and f5 works, while others do not. While comparing with the answer of Marius, I note that the output here is Matrix-type (2 curly braces), whereas from Marius is of vector-type (1 curly brace). Moreover, the option f5 gives output with the first (additional) element as 0. Could you be kind enough to explain the steps in your answers. From mathematica help, I figured out "#" (argument number) and "&" (pure function), but not very sure about various (including multiple) uses of "@". $\endgroup$
    – tomar.sk
    Mar 4, 2016 at 13:06
4
$\begingroup$

A reliable (for linear expressions) and concise way is

Normal@Last@CoefficientArrays[expr]

{-27, -6, 9, 36, 8, -12, -9, -2, 3}

but read also the rest...


I suppose you need the coefficients in some reliable order, the order of variables; maybe you already have the list of variables in the proper order and you expect to get the coefficient in the same order. If not, as already stated, you can get the variables with (Sort is not mandatory):

expr = -27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] + 
  9 Subscript[u, 1, 3] + 36 Subscript[u, 2, 1] + 
  8 Subscript[u, 2, 2] - 12 Subscript[u, 2, 3] - 
  9 Subscript[u, 3, 1] - 2 Subscript[u, 3, 2] + 3 Subscript[u, 3, 3]
vars = Sort@Variables[expr]

{Subscript[u, 1, 1], Subscript[u, 1, 2], Subscript[u, 1, 3], Subscript[u, 2, 1], Subscript[u, 2, 2], Subscript[u, 2, 3], Subscript[u, 3, 1], Subscript[u, 3, 2], Subscript[u, 3, 3]}

Now, you can get the coefficients of that expression (or of a list of expression or a list of equations) easily with CoefficientArrays. This return a list of two (or more) SparseArray.

CoefficientArrays[expr]

Mathematica graphics

The first is the constant term (0 in this case), and the second is relative to the first degree terms of the expression. You can then get the cofficient with

Normal@Last@CoefficientArrays[expr, vars]

{-27, -6, 9, 36, 8, -12, -9, -2, 3}

Rest assured that the coefficients are returned in a meaningful and consistent order.

You are not forced to collect the Variables, you can omit the second argument of CoefficientArrays

Normal@Last@CoefficientArrays[expr]

{-27, -6, 9, 36, 8, -12, -9, -2, 3}

You still get the coefficients in the predictable Variables order.

$\endgroup$
4
  • $\begingroup$ Thanks a lot for a detailed answer, and addressing the ordering issue. Could you please tell what does the constant term refer here, which results in 0? $\endgroup$
    – tomar.sk
    Mar 3, 2016 at 9:47
  • $\begingroup$ @Saku Are the terms that doesn't depend on any variable (you pass), for example in 5+x+y, x and y are variables, and 5 is what you get as first element of the returned list. If you pass as second argumen only x as "variable" you get 5+y $\endgroup$
    – unlikely
    Mar 3, 2016 at 18:58
  • $\begingroup$ Thanks a lot for explaining this. I note that in the presence of a denominator, this construction does not work because the expression is no longer a polynomial. Correct (or any other tuning resolves this case)? $\endgroup$
    – tomar.sk
    Mar 4, 2016 at 13:10
  • $\begingroup$ @Saku This method still works provide that you pass in, as a second argument, the list of variables $u$ (the variables w.r.t. which the expr is linear), for example: vars = Cases[expr, Subscript[u, _, _], \[Infinity]]; Normal@CoefficientArrays[expr, vars][[2]] $\endgroup$
    – unlikely
    Mar 7, 2016 at 11:22
3
$\begingroup$

Try this:

    expr = -27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] + 
   9 Subscript[u, 1, 3] + 36 Subscript[u, 2, 1] + 
   8 Subscript[u, 2, 2] - 12 Subscript[u, 2, 3] - 
   9 Subscript[u, 3, 1] - 2 Subscript[u, 3, 2] + 3 Subscript[u, 3, 3];


expr /. Plus -> List /. a_*Subscript[u, __] -> a

(* {-27, -6, 9, 36, 8, -12, -9, -2, 3}  *)

Have fun!

$\endgroup$
3
  • $\begingroup$ Thanks Alexei. I guess this answer is similar to Marius' answer above (perhaps a mix of both of his options?). If I understand correctly, it takes the subscripts of u for the variable a, and then produce a alone without any subscripts? $\endgroup$
    – tomar.sk
    Mar 3, 2016 at 9:53
  • $\begingroup$ @Saku Yes, it is correct $\endgroup$ Mar 4, 2016 at 7:53
  • $\begingroup$ Thanks @Alexei. The answer proposed by Marius also works for the case when the coefficient could be 1. $\endgroup$
    – tomar.sk
    Mar 4, 2016 at 11:40
0
$\begingroup$

Another way

(CoefficientRules@expr)[[All, 2]]

{-27, -6, 9, 36, 8, -12, -9, -2, 3}

Using expr as defined in the answer by Alexei Boulbitch

expr = -27 Subscript[u, 1, 1] - 6 Subscript[u, 1, 2] + 
9 Subscript[u, 1, 3] + 36 Subscript[u, 2, 1] + 
8 Subscript[u, 2, 2] - 12 Subscript[u, 2, 3] - 
9 Subscript[u, 3, 1] - 2 Subscript[u, 3, 2] + 3 Subscript[u, 3, 3];

And:

(CoefficientRules@expr)[[All, 2]] == expr /. Plus -> List /. a_*Subscript[u, __] -> a

True

$\endgroup$
3
  • $\begingroup$ Thanks TomD. Very concise. But it does not seem to work in the presence of a denominator, right? $\endgroup$
    – tomar.sk
    Mar 4, 2016 at 13:11
  • $\begingroup$ I didn't consider the denominator part of your question. It would be good if you would post an example, together with the expected outcome. But maybe (CoefficientRules@#)[[All, 2]] & /@ {Numerator@#, Denominator@#} &@expr? $\endgroup$
    – user1066
    Mar 4, 2016 at 17:18
  • $\begingroup$ Thanks. I just edited my original question to include an example of full expression. Using your updated suggestion, I get {{-27, -6, 9, 36, 8, -12, -9, -2, 3}, {16}}, which is not the expected outcome. With full expression given, I'm sure you can construct a suitable solution :) $\endgroup$
    – tomar.sk
    Mar 7, 2016 at 9:40

Your Answer

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

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