2

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]}
wolfies
  • 8,722
  • 1
  • 25
  • 54

2 Answers2

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

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]}  *)
Bob Hanlon
  • 157,611
  • 7
  • 77
  • 198
  • 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
1

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} *)
march
  • 23,399
  • 2
  • 44
  • 100
  • 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