Skip to main content

output formatting - How to keep Collect[] result in order?


For example,


Collect[(1 + x + Cos[s] x^2)^3, x]


gives the result


1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) 
+ x^4 (3 Cos[s] + 3 Cos[s]^2)

Terms of the form xn are in random order. I would like the result is to be as follows:


 1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  
x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3




Well, First Thank you very much, Jens! Second, I found there is something wrong with your statement "the HoldForm could be left out". I have tried on my mathematica 8, it turns out that the "HoldForm" is necessary . if "HoldForm" is not there, the order is still random in the output . And I tried to understand this as well as "rule" and "ruledelayed" stuff but can't figure it out. I have tried several input, each confused me. summarized as follows




  1. Replace[cx, List[x__] -> Plus[x]]


    will give


    Sequence[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]), x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3] 

    But I suppose it should give the Plus result because


    Replace[cx, List[x__] -> jjj[x]]


    gives


    jjj[1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]),  x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3]


  2. Replace[cx, List[x__] -> HoldForm@Plus[x]] gives the right result


    1 + 3 x + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) +  x^4 (3 Cos[s] + 3 Cos[s]^2) + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3


  3. Replace[cx, List[x__] :> Plus[x]] gives


    1 + 3 x + 3 x^5 Cos[s]^2 + x^6 Cos[s]^3 + x^2 (3 + 3 Cos[s]) + x^3 (1 + 6 Cos[s]) + x^4 (3 Cos[s] + 3 Cos[s]^2)


    Although it gives the right plus result, the order is wrong.





Answer



Here is an approach that doesn't rely on undocumented features or on low-level box manipulations. We're dealing with a polynomial, so we can simply collect its coefficients and arrange them any way we like as follows:


c0 = Collect[(1 + x + Cos[s] x^2)^3, x];

cx = CoefficientList[c0, x] x^Range[0, Exponent[c0, x]]


(*
==> {1, 3 x, x^2 (3 + 3 Cos[s]), x^3 (1 + 6 Cos[s]),
x^4 (3 Cos[s] + 3 Cos[s]^2), 3 x^5 Cos[s]^2, x^6 Cos[s]^3}
*)

Replace[cx, List[x__] :> HoldForm[Plus[x]]]


1+3x+x2(3+3cos(s))+x3(1+6cos(s))+x4(3cos(s)+3cos2(s))+3x5cos2(s)+x6cos3(s)




I've just assembled the desired form of the polynomial by creating a list cx of all terms up to the maximum power Exponent[c0, x], and then turning that list into a sum by means of Replace. Here, the HoldForm was put in so that the output now can be arranged in any alternative order by permuting (or, in particular, reversing) the list cx before doing the Replace:


Replace[Reverse@cx, List[x__] :> HoldForm[Plus[x]]]


x6cos3(s)+3x5cos2(s)+x4(3cos(s)+3cos2(s))+x3(1+6cos(s))+x2(3+3cos(s))+3x+1



The output is in held form, so if you apply ReleaseHold to it the order will revert back to the first version. The HoldForm could also be exploited to do further cosmetic changes on the expression, such as putting coefficients before the power of x - but you didn't ask for that.


Edit In response to a follow-up question: the Replace command has RuleDelayed (:>) instead of -> in it because the pattern indicated by x__ has to be fed into the Plus only at the time when there is actually a list of terms present. E.g., if you use List[x__] -> Plus[x] then the right-hand side is immediately evaluated to give you x as the result of Plus[x] (assuming that x hasn't been defined globally). And when you then later encounter the Replace statement it will say to feed the pattern inside List into the right-hand side that now has the form x instead of Plus[x]. That will yield something with the head Sequence corresponding to the sequence of arguments inside the given List.


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]