# Separating variables in an expression

Given a non-polynomial expression such as:

expr = x z Sin[x] Sin[y]


and that we know that the variables are:

var = {x,y,z}


... is there a neat way to express expr as:

{x Sin[x], Sin[y], z}


i.e. with the $x$ terms separated out, the $y$ terms separated out and the $z$ terms separated out ... if that separation is possible. The order does not matter ... what matters is that if the function is separable into $x$, $y$ and $z$, then that we separate the output into parcels containing just $x$, just $y$ and just $z$. If it helps, am happy to assume that expr is a product of terms.

Most of the functions I have looked at (like MonomialList or Collect) seem to assume polynomial expressions.

I was thinking of something like: expr /. Times -> List followed by some FreeQ checks, but it might be messy, and I was wondering if anyone has a neater approach?

Second example

  expr2 = x z Sin[x] Sin[y+z]


should return:

 {x Sin[x], z Sin[y+z]}

• What should happend with the non-separable parts? E.g. expr2 = x z Sin[x] Sin[y + z]? – Marius Ladegård Meyer Apr 20 '17 at 18:14
• Dupe? – J. M. will be back soon Apr 20 '17 at 18:42
• Thanks @MariusLadegårdMeyer The non-separable parts should be left NOT separated. So for your expr2, as: {x Sin[x], z Sin[y+z]} – wolfies Apr 20 '17 at 19:39

expr = x z Sin[x] Sin[y];

f = Variables[Level[#, {-1}]] &;


If the order is not important

Times @@@ GatherBy[List @@ expr, f]

(*  {x Sin[x], z, Sin[y]}  *)


If you want them ordered by variable

SortBy[Times @@@ GatherBy[List @@ expr, f], f]

(*  {x Sin[x], Sin[y], z}  *)


separate[expr_] :=
List @@ expr //. {s___, v1_, m___, v2_, e___} /;
Intersection @@ (f /@ {v1, v2}) != {} :> {s, v1*v2, m, e}


First case

expr = x z Sin[x] Sin[y];

separate[expr]

(*  {x Sin[x], z, Sin[y]}  *)


Or

separate[expr] // SortBy[#, f] &

(*  {x Sin[x], Sin[y], z}  *)


Second case

expr2 = x z Sin[x] Sin[y + z];

separate[expr2]

(*  {x Sin[x], z Sin[y + z]}  *)

• That is very nice! Thanks – wolfies Apr 20 '17 at 19:36
• @Bob Hanlon does this work on the second example he posted? – Ali Hashmi Apr 20 '17 at 19:49
• It sure does - and it is particularly elegant too! @BobHanlon 's new second solution is a treat - it took me a while to digest ... but in essence, it says: ........ "while the variables in different terms are intersecting, join the intersecting terms together ..." – wolfies Apr 23 '17 at 19:36

Probably not as elegant as you want, but it's relatively short. Using

expr = x z Sin[x] Sin[y];
vars = {x, y, z};


we do

Table[Select[expr, ! FreeQ[#1, var] &], {var, vars}]
(* {x Sin[x], Sin[y], z} *)

• Cases[expr, _Symbol, Infinity] will include numeric symbols, e.g., Pi, E, GoldenRatio. – Bob Hanlon Apr 20 '17 at 18:24
• @BobHanlon. True. Then I guess mine really only generally works if we have the variables already. I think I'll go ahead and remove that part. – march Apr 20 '17 at 18:26