How can I reorder the factors in the terms of a polynomial? Consider

poly1 = \!\(\*SubsuperscriptBox[\(x\), \(1\), \(3\)] + \*SubsuperscriptBox[\(x\), \(2\), \(3\)] + \*SubsuperscriptBox[\(x\), \(3\), \(3\)]\  - \ \(TraditionalForm\`\*SuperscriptBox[SubscriptBox[\(σ\), \(1\)], \(3\)]\)\) /.    Subscript[σ,     1] -> (Subscript[x, 1] + Subscript[x, 2] + Subscript[x, 3]) //   Expand

$$\begin{align*}-3 x_2 x_1^2-3 x_3 x_1^2-3 x_2^2 x_1-3 x_3^2 x_1-6 x_2 x_3 x_1-3 x_2 x_3^2-3 x_2^2 x_3\tag{1}\end{align*}$$

MonomialList[poly1, {Subscript[x, 1], Subscript[x, 2], Subscript[x,   3]}, "Lexicographic"]

$$\begin{align*}\left\{-3 x_1^2 x_2,-3 x_1^2 x_3,-3 x_1 x_2^2,-6 x_1 x_2 x_3,-3 x_1 x_3^2,-3 x_2^2 x_3,-3 x_2 x_3^2\right\}\tag{2}\end{align*}$$

% /. List -> Plus

$$\begin{align*}-3 x_2 x_1^2-3 x_3 x_1^2-3 x_2^2 x_1-3 x_3^2 x_1-6 x_2 x_3 x_1-3 x_2 x_3^2-3 x_2^2 x_3\tag{3}\end{align*}$$

Question1: How can I get

$$\begin{align*}-3 x_1^2 x_2-3 x_1^2 x_3-3 x_1 x_2^2-6 x_1 x_2 x_3-3 x_1 x_3^2-3 x_2^2 x_3-3 x_2 x_3^2\tag{4}\end{align*}$$

Question2: Even better if possible, how can I get

$$\begin{align*}-3\left( x_1^2 x_2+x_2^2x_1+\text{...}\right)-6 x_1 x_2 x_3\tag{5}\end{align*}$$

My goal is to keep the order of the terms in (2) unchanged when I copy (4)/(5) into an inline formula cell.

  • 1
    $\begingroup$ Does Row@MonomialList[..] work for you, or do want the TeX output? I'm not sure I'm understanding the question correctly. $\endgroup$
    – Michael E2
    Commented Aug 10, 2013 at 15:52
  • $\begingroup$ @MichaelE2 haha, yes, question1 just can be solved by Row@%, and the result can be copied to an InlineFormula Cell. $\endgroup$ Commented Aug 10, 2013 at 16:00
  • 1
    $\begingroup$ Actually Row works in this case because of the negative coefficients. For positive coefficients, you'd have to insert a "+". $\endgroup$
    – Michael E2
    Commented Aug 10, 2013 at 20:35
  • 1
    $\begingroup$ There is the undocumented PolynomialForm, but it doesn't seem to work quite right (see 9483, 15744, etc.). $\endgroup$
    – Michael E2
    Commented Aug 10, 2013 at 22:29

3 Answers 3


Question 1

As I said in a comment,

      {Subscript[x, 1], Subscript[x, 2], Subscript[x, 3]}, "Lexicographic"]

However, it works easily here because all the coefficients are negative. The following polyForm handles level 1 terms (ignores nesting). It formats the polynomial f with the monomials in a specified order. It will expand a polynomial f (via MonomialList), unless an explicit list of terms is given. It takes the same arguments as MonomialList in the case where the polynomial is passed. If the terms are passed directly in a list, they will be formatted in the same order as they occur in the list.

polyForm[f_Plus, vars_: Automatic, order_: "Lexicographic"] := 
  polyForm[MonomialList[f, vars /. Automatic :> Variables[f], order]];
polyForm[terms_List] := Module[{signs},
   signs = 
    First[Cases[#, c_?NumericQ :> Sign[c]] /. {} -> {1}] & /@ 
   PrecedenceForm[Row[Riffle[{1}~Join~signs terms,
      signs /. {1 -> "\[MediumSpace]+\[MediumSpace]", -1 -> 
         "\[MediumSpace]-\[MediumSpace]"}]], 10]

polyForm[x_, ___] := x; (* leave other stuff alone *)

Question 2

In this case you can gather the terms by the number of variables each contains:

Total[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]]

Mathematica graphics

Or you can use Row to keep them in the desired order (as in the question):

Row[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]]

Mathematica graphics

Or use polyForm, which will yield the standard spacing around the last minus sign:

polyForm[Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]]

Mathematica graphics

Mr.Wizard pointed out that my order is not the same as the desired order in the OP, something I overlooked. Here is a fix:

Factor /@ Plus @@@ GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"], 
     Length@Variables[#] &] /. poly_Plus :> polyForm[poly] // polyForm

Here is another:

MapAll[# /. poly_Plus :> polyForm[poly] &, 
 Total[Factor /@ Plus @@@ GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"], 
     Length @ Variables[#] &]]]

Mathematica graphics

For the curious, I'll share the following. Using ReplaceAll with poly_Plus :> polyForm[poly] does not work on the Total in the preceding example because is it applies the replacement at the top level first and polyForm expands the polynomial. Here is a way around that, but it does reverse the order at the top level:

Total[Factor /@ Plus @@@ 
    GatherBy[MonomialList[poly1, Variables[poly1], "Lexicographic"], 
     Length@Variables[#] &]] /. Plus -> (polyForm[List[##]] &)
  • $\begingroup$ Michael, I don't think this is quite right yet; for example, shouldn't the term −3 x1 x3^3 be the third from the right, not the second as shown above? $\endgroup$
    – Mr.Wizard
    Commented Aug 11, 2013 at 7:45
  • $\begingroup$ @Mr.Wizard Oops, that's right (assuming you mean -3 x1 x3^2) - I blithely thought the point was just to separate the kinds of terms. $\endgroup$
    – Michael E2
    Commented Aug 11, 2013 at 11:37
  • $\begingroup$ Oops.. yes, that's what I meant. $\endgroup$
    – Mr.Wizard
    Commented Aug 11, 2013 at 11:38
  • $\begingroup$ polyForm[...]//TeXForm complains withTeXForm::unspt: TeXForm of TemplateSlotSequence[1,] is not supported.. Is it possible to change polyForm so that the output can be given to TeXForm? $\endgroup$
    – Hotschke
    Commented Aug 10, 2019 at 15:34
  • $\begingroup$ @Hotschke This works on the OP's example: RowBox@First@MakeBoxes[#, StandardForm] &@ First@polyForm[ Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &]] /. "\"\[MediumSpace]-\[MediumSpace]\"" -> "-" // RawBoxes // TeXForm -- Might also need the substitution "\[MediumSpace]+\[MediumSpace]" -> "+", but it doesn't come up in this case. $\endgroup$
    – Michael E2
    Commented Aug 10, 2019 at 16:32

Related questions:

As shown in answer to the third question above you could use:

HoldForm[+##] & @@ MonomialList[poly1]

enter image description here

(+## is shorthand for Plus[##])

As already noted above and in that answer Row is not sufficient as it will not handle the signs of terms correctly.

For the second question I am borrowing part of Michael's answer, but my result is different and I believe correct:

format = HoldForm[+##] & @@ MonomialList@ # &;

Factor /@ Plus @@@ GatherBy[List @@ poly1, Length@Variables[#] &];

Plus @@ MapAt[format, %, {1, 2}]

enter image description here

The order of these terms appears to match your requested output whereas Michael's output does not.

  • 1
    $\begingroup$ Interesting___, HoldForm[+##] $\endgroup$ Commented Aug 11, 2013 at 11:47
  • $\begingroup$ @HyperGroups I fixed mine, but I must admit Mr.Wizard's is much more elegant! $\endgroup$
    – Michael E2
    Commented Aug 11, 2013 at 12:14

This can easily be done by straight manipulation with the Presentations Application, which I sell.

<< Presentations` 

step1 = poly1 // MapLevelParts[FactorOut[-3], {{1, 2, 3, 5, 6, 7}}] 
step2 = MapAt[HoldOrderForm[{1, 3, 2, 5, 4, 6}], step1, {{2, 2}}]

enter image description here enter image description here

FactorOut will factor an arbitrary expression out of an existing expression - even if it is not initially in the expression. MapLevelParts will map a function to a set of level parts in an expression (usually a sum or product or sometimes a list). It applies as a whole to the sub sum, product or list. In your example the level parts are at level 1 but it is also possible to specify a set of level parts at a deeper position.

  • $\begingroup$ This also doesn't seem to match the requested order. Compare your result to mine. $\endgroup$
    – Mr.Wizard
    Commented Aug 11, 2013 at 8:44
  • $\begingroup$ @ Mr. Wizard. Well that is easy to fix with another Presentations routine, HoldOrderForm, which allows the permutation of terms or factors. However, the first form does have the advantage of being a normal non-held Mathematica expression. $\endgroup$
    – David Park
    Commented Aug 11, 2013 at 16:28

Your Answer

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

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