20
$\begingroup$

I have a lot of variables: $a,b,c,d, \ldots $ I want to clear the values of all of them except $b$. It's really lengthy to write

Clear[a]; 
Clear[c];
...

Is there any command which clears all variables except a chosen one?

$\endgroup$
28
$\begingroup$

An alternative that doesn't require protecting or using private contexts:

Clear @@ DeleteCases[Names@"`*", "b"];

To keep a few (as suggested in comments) replace "b" with "b"|"g"|"h".

$\endgroup$
  • $\begingroup$ Nice one, frog +1. What about the Timings? No impact? $\endgroup$ – Dr. belisarius Sep 23 '12 at 8:38
  • $\begingroup$ @belisarius Timings? I don't really see a reason for there to be a significant difference in timings... $\endgroup$ – rm -rf Sep 23 '12 at 16:25
  • $\begingroup$ @rm -rf, I was wondering how to use this technique if there are more than one variables? $\endgroup$ – preeti Jan 21 '14 at 2:38
  • 1
    $\begingroup$ @preeti You mean you want to delete all variables except a few specific ones? You can replace "b" above with your variables separated by |, like "b" | "c" | "d". $\endgroup$ – rm -rf Jan 21 '14 at 2:59
  • $\begingroup$ Excellent. If you could include that in your answer, it will make it easy for searching.Thanks. $\endgroup$ – preeti Jan 21 '14 at 4:08
7
$\begingroup$

The solution is to first protect b, then clear all variables in current context, and then unprotect b again:

Protect[b];Clear[Evaluate[$Context<>"*"]];Unprotect[b]

By protecting b, you prevent it from getting cleared (Mathematica will complain, but do the right thing anyway). Note that the $Context construction makes sure that you clear the correct symbols if you have e.g. chosen to have an unique context for your notebook.

Also note that if you have defined variables in other contexts, too (e.g. using packages) which you also want to have cleared, you'll have to explicitly clear those contexts as well.

$\endgroup$
6
$\begingroup$

You may want to place your special variable(s) in a separate context and then only clear Global`*. This is not the same as belisarius' recommendation. Instead create the variable b in a different context to begin with and append this context to the context path:

AppendTo[$ContextPath, "special`"];

special`b = 5; (* fully qualified name on first use *)

a = 1;
c = 2;

a + b + c
8
Clear["Global`*"]

a + b + c
5 + a + c
$\endgroup$
4
$\begingroup$

What I would to is quite simple: simply Block the variable you don't want to clear:

a=1;b=2;c=3;
Block[{a},
   Clear[a,b,c]
]

{a, b, c}

(* {1, b, c}  *)

This solution allows you to deal with symbols rather than their string names. You can get fancier and create a closure which would encapsulate your original list of symbols and take those symbols which should not be cleared:

ClearAll[makeClearF];
SetAttributes[makeClearF, HoldAll];
makeClearF[syms__Symbol] :=
     Function[Null, Block[{##}, Clear[syms]], HoldAll];

So that, for example

clear = makeClearF[a, b, c];

a=1;b=2;c=3;
clear[a]; (* clear all but a *)
{a,b,c}

(* {1,b,c}  *)

or

a=1;b=2;c=3;
clear[b,c]; (* clear all but b and c *)
{a,b,c}

(*  {a,2,3}  *)

I want to stress that this solution is different from those based on string names in that parsing is not involved. Which one is a better fit depends on the circumstances.

$\endgroup$
3
$\begingroup$

Also, preserve it in a "private" context prior to the cleaning:

b = 1;
myCtx`b = b;
Clear["Global`*"];
b = myCtx`b
(* 1 *)
$\endgroup$
1
$\begingroup$

One other alternative is to Compress[b] and copy the resulting string to your clipboard, then do the global clear or kernel quit, and then b=Uncompress["..."]. This is not the most elegant solution, obviously, but it's a useful technique to be aware of.

$\endgroup$

Your Answer

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