I need to execute this function thousands of times, and the faster, the better. I came up with two versions, but wanted to see if you can come up with an even faster way. Is there a better way?

I use the list:


And the function checks if my expression contains all those symbols:


First version:


Second version (faster):

  • $\begingroup$ Thanks for accepting my answer. On the other hand, I would recommend you to wait about one day before accepting an answer. There may be better answers coming out. $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 17:06
  • $\begingroup$ Yes, you were right. I'll unaccept and wait a little more. But yours seems very promissing. Thanks again. $\endgroup$ Feb 13, 2014 at 17:34

3 Answers 3


I am not sure if the return value of Variables meets your standard. If so, this works.

Complement[symbolsList, Variables@expression] == {}

 Do[Complement[symbolsList, Variables@expression] == {};, {200000}]

{0.575185, Null}

As @Szabolcs commented, Level[expression, {-1}] may be a nice alternative. And it's actually faster in this example:

 Do[Complement[symbolsList, Level[expression, {-1}]] == {};, {200000}]

{0.365893, Null}

They have similar speed to the OP's solution though.

AbsoluteTiming@Do[ContainsAllSymbols2[expression], {200000}]

{0.942182, Null}

  • $\begingroup$ +1, instead of Variables you can also use Level[expr, {-1}], which will give more control over what to include. (E.g. if you need heads, Level has an option for that.) $\endgroup$
    – Szabolcs
    Feb 13, 2014 at 16:23
  • $\begingroup$ Could you please compare with the timings of my second solution? I think my solution works faster if the expression is big, since it breaks on the first non occurence of a symbol on symbolsList. Your computer seems to be a lot faster than mine :). $\endgroup$ Feb 13, 2014 at 16:40
  • $\begingroup$ In your particular example they have comparable speed. If there are symbols which doesn't exist, yours may be faster. $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 16:50
  • $\begingroup$ @Giovanni I also noticed your code should be FreeQ, not !FreeQ. Benchmark is updated. $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 17:01
  • $\begingroup$ Corrected there, thanks! Your code seems faster in all situations after I corrected the bug. $\endgroup$ Feb 13, 2014 at 17:06

Here;s one approach:

expression = {r^2 + A*b - 3};
vars1 = {r, A, b};
vars2 = {r, A, w, d};
Total[Boole[FreeQ[expression, #] & /@ vars1]] == 0

For example, this returns True for vars1 and False for vars2.

  • $\begingroup$ It's an alternative, timed between my first and second approaches. $\endgroup$ Feb 13, 2014 at 17:09

Of all the approaches not yet presented here this one seems to be the fastest:

containsAllSymbols[expr_, s_] := !FreeQ[expr, s]

containsAllSymbols[expr_, first_, rest__] :=
And[!FreeQ[expr, first], containsAllSymbols[expr, rest]]

EDIT: I claimed this to be faster than Complement[symbolsList, Variables@expression] but I was wrong, sorry.

Note that this approach does not use List wrapper. You might want to additionally define

ContainsAllSymbols[expr_, {s__Symbol}] := containsAllSymbols[expr, s]

I think it's worth noting that And[False, (rest)] does not evaluate (rest), a well as Or[True, (rest)].

UPD: As observed by Yi Wang in commments, you might want to use this method if you suspect that some symbols are not in the expression. Suspicious symbols should then be placed first in the symbols list.

  • $\begingroup$ Yours is faster than mine when I tested. However, if I use the OP's test data, symbolsList = {r, A, b}, expression = r^2 + A*b - 3, I got False for containsAllSymbols[expression, symbolsList]. I think it is supposed to be True. Or did I miss anything? $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 21:23
  • $\begingroup$ Sorry, I see. symbolsList should be written as Sequence@@symbolsList. Then the result is correct but it takes also a bit longer. $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 21:25
  • $\begingroup$ @YiWang My fault. I didn't check my data set as well, so I erroneously concluded it was faster. :-) Still, I think it's worth to be posted, mostly for the sake of And[False, …] trick. $\endgroup$
    – akater
    Feb 13, 2014 at 21:29
  • $\begingroup$ Thanks for explanation! This is a very interesting method. Nice to see! Also I guess for some data sets yours may be faster than mine (where And[False, ...] quits early). I didn't test though. $\endgroup$
    – Yi Wang
    Feb 13, 2014 at 21:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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