Is there a faster way of evaluating every combination of booleans in an if statement in python?
Question:
If I have 4 booleans e.g
if ((a(x) == True) and (b(x) == True) and (c(x) == True) and (d(x) == True)
then I want to do something different for each combination including when only 3 of them are true (including which ones), 2…, then only each 1… etc…
Is there a quicker way than writing a bunch of elifs?
Possibly using a loop
Answers:
You can count the number of True booleans using arithmetic operators
numTrue = (a(x) == True) + (b(x) == True) + (c(x) == True) + (d(x) == True)
if numTrue==4:
# foo
elif numTrue==3:
# bar
elif numTrue==2:
# ...
elif numTrue==1:
#...
else:
# ...
Note that I kept your redundant structure x==True
, which, from a boolean point a view is just a convoluted version of x
. But at least, now, I am sure that your booleans (since I know nothing of a(x)
and others) are True
or False
, not other truthiness are falseness.
You could build a lookup table using a dict
:
lookup = {(True, True, True, True): func_1,
(True, True, True, False): func_2,
(True, True, False, True): func_3,
... etc.
}
func = lookup[a(x), b(x), c(x), d(x)]
func()
including when only 3 of them are true
This suggests you’d like to know that N of the 4 values are true:
vals = a(x), b(x), c(x), d(x)
num_true = sum(map(bool, vals))
Given such a vector of booleans, there are 2 ** 4 == 16
possibilities.
We can put 16 values into a dict
named d
and go from there.
k = " ".join(map(str, map(int, map(bool, vals))))
print(d[k])
If the identities don’t matter to you,
then sort so we have fewer than 16 possibilities:
k = " ".join(sorted(map(str, map(int, map(bool, vals)))))
The solution with the lookup table is great but if you wanted to do something that takes less memory and around the same speed. You can use the if statement results to build on each other this way you’d only have 2^4(16) cases i.e:
if (a(x)):
if(b(x):
if(c(x)):
if(d(x)):
#do x
else:
#do y
else:
if (d(x)):
#do z
else:
#do w
#...
If I have 4 booleans e.g
if ((a(x) == True) and (b(x) == True) and (c(x) == True) and (d(x) == True)
then I want to do something different for each combination including when only 3 of them are true (including which ones), 2…, then only each 1… etc…
Is there a quicker way than writing a bunch of elifs?
Possibly using a loop
You can count the number of True booleans using arithmetic operators
numTrue = (a(x) == True) + (b(x) == True) + (c(x) == True) + (d(x) == True)
if numTrue==4:
# foo
elif numTrue==3:
# bar
elif numTrue==2:
# ...
elif numTrue==1:
#...
else:
# ...
Note that I kept your redundant structure x==True
, which, from a boolean point a view is just a convoluted version of x
. But at least, now, I am sure that your booleans (since I know nothing of a(x)
and others) are True
or False
, not other truthiness are falseness.
You could build a lookup table using a dict
:
lookup = {(True, True, True, True): func_1,
(True, True, True, False): func_2,
(True, True, False, True): func_3,
... etc.
}
func = lookup[a(x), b(x), c(x), d(x)]
func()
including when only 3 of them are true
This suggests you’d like to know that N of the 4 values are true:
vals = a(x), b(x), c(x), d(x)
num_true = sum(map(bool, vals))
Given such a vector of booleans, there are 2 ** 4 == 16
possibilities.
We can put 16 values into a dict
named d
and go from there.
k = " ".join(map(str, map(int, map(bool, vals))))
print(d[k])
If the identities don’t matter to you,
then sort so we have fewer than 16 possibilities:
k = " ".join(sorted(map(str, map(int, map(bool, vals)))))
The solution with the lookup table is great but if you wanted to do something that takes less memory and around the same speed. You can use the if statement results to build on each other this way you’d only have 2^4(16) cases i.e:
if (a(x)):
if(b(x):
if(c(x)):
if(d(x)):
#do x
else:
#do y
else:
if (d(x)):
#do z
else:
#do w
#...