I have two boolean lists, e.g.,
x=[True,True,False,False]
y=[True,False,True,False]
I want to AND these lists together, with the expected o
Instead of using
[a and b for a, b in zip(x, y)]
one could just use the possibility of numpy to multiply bool-values:
(np.array(x)*np.array(y))
>> array([ True, False, False, False], dtype=bool)
Or do I overlook a special case?
In addition to what @Martijn Pieters has answered, I would just add the following code to explain and
and or
operations in action.
and
returns the first falsy value encountered else the last evaluated argument.
Similarly or
returns the first truthy value encountered else the last evaluated argument.
nl1 = [3,3,3,3,0,0,0,0]
nl2 = [2,2,0,0,2,2,0,0]
nl3 = [1,0,1,0,1,0,1,0]
and_list = [a and b and c for a,b,c in zip(nl1,nl2,nl3)]
or_list = [a or b or c for a,b,c in zip(nl1,nl2,nl3)]
Values are
and_list = [1, 0, 0, 0, 0, 0, 0, 0]
or_list = [3, 3, 3, 3, 2, 2, 1, 0]
Thanks for the answer @Martijn Pieters and @Tony. I dig into the timing of the various options we have to make the AND of two lists and I would like to share my results, because I found them interesting.
Despite liking a lot the pythonic way [a and b for a,b in zip(x,y) ], turns out really slow. I compare with a integer product of arrays (1*(array of bool)) * (1*(array of bool)) and it turns out to be more than 10x faster
import time
import numpy as np
array_to_filter = np.linspace(1,1000000,1000000) # 1 million of integers :-)
value_limit = 100
cycles = 100
# METHOD #1: [a and b for a,b in zip(x,y) ]
t0=time.clock()
for jj in range(cycles):
x = array_to_filter<np.max(array_to_filter)-value_limit # filter the values > MAX-value_limit
y = array_to_filter>value_limit # filter the values < value_limit
z= [a and b for a,b in zip(x,y) ] # AND
filtered = array_to_filter[z]
print('METHOD #1 = %.2f s' % ( (time.clock()-t0)))
# METHOD 1*(array of bool) AND 1*(array of bool)
t0=time.clock()
for jj in range(cycles):
x = 1*(array_to_filter<np.max(array_to_filter)-value_limit) # filter the values > MAX-value_limit
y = 1*(array_to_filter>value_limit) # filter the values < value_limit
z = x*y # AND
z = z.astype(bool) # convert back to array of bool
filtered = array_to_filter[z]
print('METHOD #2 = %.2f s' % ( (time.clock()-t0)))
The results are
METHOD #1 = 15.36 s
METHOD #2 = 1.85 s
The speed is almost affected equally by the size of the array or by the number of cycles.
I hope I helped someone code to be faster. :-)