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]}
  • 1
    $\begingroup$ What should happend with the non-separable parts? E.g. expr2 = x z Sin[x] Sin[y + z]? $\endgroup$ Apr 20, 2017 at 18:14
  • 1
    $\begingroup$ Dupe? $\endgroup$ Apr 20, 2017 at 18:42
  • $\begingroup$ Thanks @MariusLadegårdMeyer The non-separable parts should be left NOT separated. So for your expr2, as: {x Sin[x], z Sin[y+z]} $\endgroup$
    – wolfies
    Apr 20, 2017 at 19:39

2 Answers 2

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}  *)

EDIT: To address both cases

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];


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


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

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

Second case

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


(*  {x Sin[x], z Sin[y + z]}  *)
  • $\begingroup$ That is very nice! Thanks $\endgroup$
    – wolfies
    Apr 20, 2017 at 19:36
  • $\begingroup$ @Bob Hanlon does this work on the second example he posted? $\endgroup$
    – Ali Hashmi
    Apr 20, 2017 at 19:49
  • $\begingroup$ 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 ..." $\endgroup$
    – wolfies
    Apr 23, 2017 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} *)
  • $\begingroup$ Cases[expr, _Symbol, Infinity] will include numeric symbols, e.g., Pi, E, GoldenRatio. $\endgroup$
    – Bob Hanlon
    Apr 20, 2017 at 18:24
  • $\begingroup$ @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. $\endgroup$
    – march
    Apr 20, 2017 at 18:26

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.