7
$\begingroup$

========== motivation ===========

Suppose, for example, I have an incoming expression like

 m = (3-I)x + 4(x y)/(Cos[y]) 

I want to find all the symbols in the expression ("x" and "y" in this case) without a priori knowledge of what symbols may appear in m.
Perhaps then I want to do something to the symbols, for example, transform each symbol #:

# -> u*# 

i.e. I want to obtain from m:

(3-I)u x + 4(u^2 x y)/(Cos[u y]) 

In this case, I can take this result, expand in u and unitize to get:

Series[(3-I)u x + 4(u^2 x y)/(Cos[u y]), {u,0,1}]/.u->1 

a series expansion to first order in both x and y, where terms x^2, y^2, and x y are dropped.

==============================================================

This is just one example though, in general, I want to know how to find the symbols in an expression and do something to them.

I've tried things similar to

 test = Expand[# /. Not@NumericQ :> ReplaceAll[#, z -> u z]] &; (5-3 I)x + 2 y^2 //test 

But this just returns the input unchanged, I would like it to return

 (5-3 I)u x + 2 u^2 y^2 

Any help?

$\endgroup$
1
  • $\begingroup$ I feel that this question should be closed as a duplicate of (30038) but there is just enough wiggle room that I don't wish to act alone. If anyone agrees or disagrees please comment. $\endgroup$ Commented Jul 2, 2014 at 6:55

4 Answers 4

13
$\begingroup$
m = (3 - I) x + 4 (x y)/(Cos[y]); Variables@Level[m, {-1}] (*{x, y}*) 
$\endgroup$
2
  • $\begingroup$ nice use of Variables $\endgroup$ Commented Jul 1, 2014 at 19:43
  • $\begingroup$ @Nasser it should look rather familiar. $\endgroup$ Commented Jul 2, 2014 at 6:49
5
$\begingroup$

"...in general, I want to know how to find the symbols in an expression..."

m = (3 - I) x + 4 (x y)/(Cos[y]); sym = DeleteDuplicates@Cases[m, _Symbol, Infinity] 

{x, y}

"... and do something to them"

m /. MapThread[Rule, {sym, {u, v}}] 

(3 - I) u + 4 u v Sec[v]

$\endgroup$
3
  • $\begingroup$ Great! Even m /. Function[{sym},MapThread[Rule, {sym,Symbol["x" <> ToString[#]] & /@ Range[Length@sym]}]][sym] $\endgroup$ Commented Jul 1, 2014 at 19:16
  • $\begingroup$ This does not work. Cases[m, _Symbol, Infinity] will output an empty list, instead of {m} as it should. Using Cases[m, _Symbol, {-1}] seems to do the trick. $\endgroup$ Commented Dec 21, 2017 at 4:50
  • $\begingroup$ @Myridium Cases[m,_Symbol, All] also works but maybe it's slower I do not know. It's maybe also important to mention that Cases[Pi,_Symbol,All] outputs {Pi} as Pi has head Symbol. However using Variables from the other answer with Level[Pi, {-1}] // Variables leads to an empty list. Thus, the two methods are not equivalent $\endgroup$ Commented Mar 30, 2023 at 5:45
4
$\begingroup$
m = (3 - I) x + 4 (x y)/(Cos[y Pi]); 

Since

Head /@ {Pi, E, GoldenRatio} (* and others *) 

{Symbol, Symbol, Symbol}

Cases must test for more than just Symbol

m /. Thread[(var = Cases[m, _Symbol?(! NumericQ[#] &), Infinity] // Union) -> u*var] 

(3 - I)*u*x + 4*u^2*x*y* Sec[Pi*u*y]

$\endgroup$
3
  • $\begingroup$ +1, I think it safe to assume this is what the OP intended for symbol capture. $\endgroup$ Commented Jul 2, 2014 at 1:44
  • 1
    $\begingroup$ I agree, you can separate them also by context since built in symbols have System` while x is Global` $\endgroup$ Commented Jul 2, 2014 at 5:58
  • $\begingroup$ @BobHanlon Using Variables (like Algohi did) eliminates NumericQ $\endgroup$ Commented Jul 2, 2014 at 9:03
1
$\begingroup$
m = (3 - I) x + 4 (x y)/Cos[y]; lev = Level[m, {-1}] Union@Cases[lev, _Symbol] (* {x, y} *) 
$\endgroup$
1
  • $\begingroup$ .. just saw eldo post after hitting post.... This is a little different may be. In Mathematica, we should always try to come up with 10 different ways to solve something :) $\endgroup$ Commented Jul 1, 2014 at 19:10

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.