How to toggle a value?

What is the most efficient way to toggle between 0 and 1?

1

17 Answers

Solution using NOT

If the values are boolean, the fastest approach is to use the not operator:

>>> x = True >>> x = not x # toggle >>> x False >>> x = not x # toggle >>> x True >>> x = not x # toggle >>> x False 

Solution using subtraction

If the values are numerical, then subtraction from the total is a simple and fast way to toggle values:

>>> A = 5 >>> B = 3 >>> total = A + B >>> x = A >>> x = total - x # toggle >>> x 3 >>> x = total - x # toggle >>> x 5 >>> x = total - x # toggle >>> x 3 

Solution using XOR

If the value toggles between 0 and 1, you can use a bitwise exclusive-or:

>>> x = 1 >>> x ^= 1 >>> x 0 >>> x ^= 1 >>> x 1 

The technique generalizes to any pair of integers. The xor-by-one step is replaced with a xor-by-precomputed-constant:

>>> A = 205 >>> B = -117 >>> t = A ^ B # precomputed toggle constant >>> x = A >>> x ^= t # toggle >>> x -117 >>> x ^= t # toggle >>> x 205 >>> x ^= t # toggle >>> x -117 

(This idea was submitted by Nick Coghlan and later generalized by @zxxc.)

Solution using a dictionary

If the values are hashable, you can use a dictionary:

>>> A = 'xyz' >>> B = 'pdq' >>> d = {A:B, B:A} >>> x = A >>> x = d[x] # toggle >>> x 'pdq' >>> x = d[x] # toggle >>> x 'xyz' >>> x = d[x] # toggle >>> x 'pdq' 

Solution using a conditional expression

The slowest way is to use a conditional expression:

>>> A = [1,2,3] >>> B = [4,5,6] >>> x = A >>> x = B if x == A else A >>> x [4, 5, 6] >>> x = B if x == A else A >>> x [1, 2, 3] >>> x = B if x == A else A >>> x [4, 5, 6] 

Solution using itertools

If you have more than two values, the itertools.cycle() function provides a generic fast way to toggle between successive values:

>>> import itertools >>> toggle = itertools.cycle(['red', 'green', 'blue']).next >>> toggle() 'red' >>> toggle() 'green' >>> toggle() 'blue' >>> toggle() 'red' >>> toggle() 'green' >>> toggle() 'blue' 

Note that in Python 3 the next() method was changed to __next__(), so the first line would be now written as toggle = itertools.cycle(['red', 'green', 'blue']).__next__

6

I always use:

p^=True 

If p is a boolean, this switches between true and false.

6

Here is another non intuitive way. The beauty is you can cycle over multiple values and not just two [0,1]

For Two values (toggling)

>>> x=[1,0] >>> toggle=x[toggle] 

For Multiple Values (say 4)

>>> x=[1,2,3,0] >>> toggle=x[toggle] 

I didn't expect this solution to be almost the fastest too

>>> stmt1=""" toggle=0 for i in xrange(0,100): toggle = 1 if toggle == 0 else 0 """ >>> stmt2=""" x=[1,0] toggle=0 for i in xrange(0,100): toggle=x[toggle] """ >>> t1=timeit.Timer(stmt=stmt1) >>> t2=timeit.Timer(stmt=stmt2) >>> print "%.2f usec/pass" % (1000000 * t1.timeit(number=100000)/100000) 7.07 usec/pass >>> print "%.2f usec/pass" % (1000000 * t2.timeit(number=100000)/100000) 6.19 usec/pass stmt3=""" toggle = False for i in xrange(0,100): toggle = (not toggle) & 1 """ >>> t3=timeit.Timer(stmt=stmt3) >>> print "%.2f usec/pass" % (1000000 * t3.timeit(number=100000)/100000) 9.84 usec/pass >>> stmt4=""" x=0 for i in xrange(0,100): x=x-1 """ >>> t4=timeit.Timer(stmt=stmt4) >>> print "%.2f usec/pass" % (1000000 * t4.timeit(number=100000)/100000) 6.32 usec/pass 
6

The not operator negates your variable (converting it into a boolean if it isn't already one). You can probably use 1 and 0 interchangeably with True and False, so just negate it:

toggle = not toggle 

But if you are using two arbitrary values, use an inline if:

toggle = 'a' if toggle == 'b' else 'b' 
2

Just between 1 and 0, do this

1-x 

x can take 1 or 0

1

Trigonometric approach, just because sin and cos functions are cool.

enter image description here

>>> import math >>> def generator01(): ... n=0 ... while True: ... yield abs( int( math.cos( n * 0.5 * math.pi ) ) ) ... n+=1 ... >>> g=generator01() >>> g.next() 1 >>> g.next() 0 >>> g.next() 1 >>> g.next() 0 
0

Surprisingly nobody mention good old division modulo 2:

In : x = (x + 1) % 2 ; x Out: 1 In : x = (x + 1) % 2 ; x Out: 0 In : x = (x + 1) % 2 ; x Out: 1 In : x = (x + 1) % 2 ; x Out: 0 

Note that it is equivalent to x = x - 1, but the advantage of modulo technique is that the size of the group or length of the interval can be bigger then just 2 elements, thus giving you a similar to round-robin interleaving scheme to loop over.

Now just for 2, toggling can be a bit shorter (using bit-wise operator):

x = x ^ 1 
2

one way to toggle is by using Multiple assignment

>>> a = 5 >>> b = 3 >>> t = a, b = b, a >>> t[0] 3 >>> t = a, b = b, a >>> t[0] 5 

Using itertools:

In [12]: foo = itertools.cycle([1, 2, 3]) In [13]: next(foo) Out[13]: 1 In [14]: next(foo) Out[14]: 2 In [15]: next(foo) Out[15]: 3 In [16]: next(foo) Out[16]: 1 In [17]: next(foo) Out[17]: 2 
0

The easiest way to toggle between 1 and 0 is to subtract from 1.

def toggle(value): return 1 - value 

Using exception handler

>>> def toogle(x): ... try: ... return x/x-x/x ... except ZeroDivisionError: ... return 1 ... >>> x=0 >>> x=toogle(x) >>> x 1 >>> x=toogle(x) >>> x 0 >>> x=toogle(x) >>> x 1 >>> x=toogle(x) >>> x 0 

Ok, I'm the worst:

enter image description here

import math import sys d={1:0,0:1} l=[1,0] def exception_approach(x): try: return x/x-x/x except ZeroDivisionError: return 1 def cosinus_approach(x): return abs( int( math.cos( x * 0.5 * math.pi ) ) ) def module_approach(x): return (x + 1) % 2 def subs_approach(x): return x - 1 def if_approach(x): return 0 if x == 1 else 1 def list_approach(x): global l return l[x] def dict_approach(x): global d return d[x] def xor_approach(x): return x^1 def not_approach(x): b=bool(x) p=not b return int(p) funcs=[ exception_approach, cosinus_approach, dict_approach, module_approach, subs_approach, if_approach, list_approach, xor_approach, not_approach ] f=funcs[int(sys.argv[1])] print "\n\n\n", f.func_name x=0 for _ in range(0,100000000): x=f(x) 
0

How about an imaginary toggle that stores not only the current toggle, but a couple other values associated with it?

toggle = complex.conjugate 

Store any + or - value on the left, and any unsigned value on the right:

>>> x = 2 - 3j >>> toggle(x) (2+3j) 

Zero works, too:

>>> y = -2 - 0j >>> toggle(y) (-2+0j) 

Easily retrieve the current toggle value (True and False represent + and -), LHS (real) value, or RHS (imaginary) value:

>>> import math >>> curr = lambda i: math.atan2(i.imag, -abs(i.imag)) > 0 >>> lhs = lambda i: i.real >>> rhs = lambda i: abs(i.imag) >>> x = toggle(x) >>> curr(x) True >>> lhs(x) 2.0 >>> rhs(x) 3.0 

Easily swap LHS and RHS (but note that the sign of the both values must not be important):

>>> swap = lambda i: i/-1j >>> swap(2+0j) 2j >>> swap(3+2j) (2+3j) 

Easily swap LHS and RHS and also toggle at the same time:

>>> swaggle = lambda i: i/1j >>> swaggle(2+0j) -2j >>> swaggle(3+2j) (2-3j) 

Guards against errors:

>>> toggle(1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: descriptor 'conjugate' requires a 'complex' object but received a 'int' 

Perform changes to LHS and RHS:

>>> x += 1+2j >>> x (3+5j) 

...but be careful manipulating the RHS:

>>> z = 1-1j >>> z += 2j >>> z (1+1j) # whoops! toggled it! 

Variables a and b can be ANY two values, like 0 and 1, or 117 and 711, or "heads" and "tails". No math is used, just a quick swap of the values each time a toggle is desired.

a = True b = False a,b = b,a # a is now False a,b = b,a # a is now True 

I use abs function, very useful on loops

x = 1 for y in range(0, 3): x = abs(x - 1) 

x will be 0.

1

Let's do some frame hacking. Toggle a variable by name. Note: This may not work with every Python runtime.

Say you have a variable "x"

>>> import inspect >>> def toggle(var_name): >>> frame = inspect.currentframe().f_back >>> vars = frame.f_locals >>> vars[var_name] = 0 if vars[var_name] == 1 else 1 >>> x = 0 >>> toggle('x') >>> x 1 >>> toggle('x') >>> x 0 

If you are dealing with an integer variable, you can increment 1 and limit your set to 0 and 1 (mod)

X = 0 # or X = 1 X = (X + 1)%2 

Switching between -1 and +1 can be obtained by inline multiplication; used for calculation of pi the 'Leibniz' way (or similar):

sign = 1 result = 0 for i in range(100000): result += 1 / (2*i + 1) * sign sign *= -1 print("pi (estimate): ", result*4) 

You can make use of the index of lists.

def toggleValues(values, currentValue): return values[(values.index(currentValue) + 1) % len(values)] > toggleValues( [0,1] , 1 ) > 0 > toggleValues( ["one","two","three"] , "one" ) > "two" > toggleValues( ["one","two","three"] , "three") > "one" 

Pros: No additional libraries, self.explanatory code and working with arbitrary data types.

Cons: not duplicate-save. toggleValues(["one","two","duped", "three", "duped", "four"], "duped") will always return "three"

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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

You Might Also Like