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$ – Marius Ladegård Meyer Apr 20 '17 at 18:14
  • 1
    $\begingroup$ Dupe? $\endgroup$ – J. M.'s ennui Apr 20 '17 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 '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}  *)

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 '17 at 19:36
  • $\begingroup$ @Bob Hanlon does this work on the second example he posted? $\endgroup$ – Ali Hashmi Apr 20 '17 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 '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} *)
  • $\begingroup$ Cases[expr, _Symbol, Infinity] will include numeric symbols, e.g., Pi, E, GoldenRatio. $\endgroup$ – Bob Hanlon Apr 20 '17 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 '17 at 18:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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