Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I'm looking for a way to extract a list of variables from an expression, for example with an input like:

Leff= (mc dm^2 + mc/12*(h^2 + 3 R^2) + ma da^2 + ma/12 La^2)/(mc dm + ma da)

I want this output:

{mc, dm, ma, da, La, h, R}.

The built-in Mathematica function Variables can do this but doesn't work with more complex expressions containing trascendental functions. Any help would be very appreciated.

share|improve this question
    
Wouldn't it be more natural to use { c, d, a, b, L, h, R} instead of unreasonable and awful {mc, dm, ma, da, La, h, R} ? –  Artes Mar 13 '13 at 20:24
2  
@Artes Mnemonics can often be helpful, as well as using variables whose names are as close as possible to a formula as printed in a textbook or paper. Let's blame the paper authors and not the coders for bad variable names! –  whuber Mar 13 '13 at 20:41
    
Related: (15153) –  Mr.Wizard Mar 13 '13 at 23:24

4 Answers 4

up vote 12 down vote accepted

Assuming you don't have any built-in symbols in that list, you could simply do:

DeleteDuplicates@Cases[Leff, _Symbol, Infinity]
(* {da, ma, dm, mc, La, h, R} *)

If you do have symbols from built-in contexts or packages, you can simply pick out only those that are in the Global` context with:

With[{globalQ = Context@# === "Global`" &},
    DeleteDuplicates@Cases[Leff, _Symbol?globalQ, Infinity]
]

If you have a different default working context (e.g. local to notebook/cell or in a package), change the pattern test to the following, instead of globalQ:

currentContextQ = Context@# === $Context &
share|improve this answer
    
Thank you very much, this is exactly what I was looking for. –  John Mar 13 '13 at 20:32

If you have even more complicated expressions, you might want to use Heads -> True.

expr = {f, Subscript[g, i], h[i[j[a, b]]], s'[t] == u[t] + v[t]};

Union@Cases[expr, Except[__Symbol?(Context@# === "System`" &), _Symbol],
    {1, Infinity}, Heads -> True]
{a, b, f, g, h, i, j, s, t, u, v}

Without checking heads:

Union@Cases[expr, Except[__Symbol?(Context@# === "System`" &), _Symbol], {1, Infinity}]
{a, b, f, g, i, t}
share|improve this answer
2  
This is the method I would use, expect perhaps as Union @ Cases[Leff, s_Symbol /; Context[s] =!= "System`", -1] –  Mr.Wizard Mar 13 '13 at 23:11
    
@Mr.Wizard I've tried to provide code that is sufficiently different from rm-rf-s version not to give room for any comments on plagiarism :) –  István Zachar Mar 14 '13 at 7:46
    
Thank you, the expressions I usually work with are not so complicated but I might need this sometimes. –  John Mar 14 '13 at 15:19

The below code for getAllVariables was lifted without attribution from some StackOverflow post.

headlist = {Or, And, Equal, Unequal, Less, LessEqual, Greater, 
   GreaterEqual, Inequality};

getAllVariables[f_?NumericQ] := Sequence[]
getAllVariables[{}] := Sequence[]
getAllVariables[t_] /; MemberQ[headlist, t] := Sequence[]

getAllVariables[ll_List] := 
 Flatten[Union[Map[getAllVariables[#] &, ll]]]

getAllVariables[Derivative[n_Integer][f_][arg__]] := 
 getAllVariables[{arg}]

getAllVariables[f_Symbol[arg__]] := 
 Module[{fvars}, 
  If[MemberQ[Attributes[f], NumericFunction] || MemberQ[headlist, f], 
   fvars = getAllVariables[{arg}],(*else*)fvars = f[arg]];
  fvars]

getAllVariables[other_] := other

Example:

Leff = (mc dm^2 + mc/12*(h^2 + 3 R^2) + ma da^2 + ma/12 La^2)/(mc dm +
     ma da)
getAllVariables[Leff]

(* Out[254]= {da, ma, dm, mc, ma, da, ma, La, mc, dm, mc, h, R} *)
share|improve this answer
    
Daniel, since questions are generally not being migrated any longer and since these valuable posts ultimately fall outside our control, why don't you repost your method as a full answer? –  Mr.Wizard Mar 16 '13 at 14:15
    
@Mr.Wizard Done. (But if you were a real wizard, couldn't you just make it magically happen?) –  Daniel Lichtblau Mar 16 '13 at 20:44
expr = (mc dm^2 + mc/12*(h^2 + 3 R^2) + ma da^2 + ma/12 La^2)/(mc dm + ma da); 
Level[expr, {-1}] /. x_?NumericQ :> (## &[]) // DeleteDuplicates
(* {da,ma,dm,mc,La,h,R} *)
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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