I have two lists:
X = [True,False]
Y = [True,True]
I am trying to compare X[0] with Y[0] and X[1] with Y[1].
I tried
in [7]: X and Y
Out[7]: [True, True]
but the result I was expecting was [True,False].
What should I be doing?
This is a perfect opportunity to use map, because and can be represented with a built-in function:
import operator
X = [True,False]
Y = [True,True]
map(operator.and_, X,Y)
#=> [True, False]
The reason why you get the behaviour you did is that and performs operations on the operands as if they had bool applied to them. All non-empty lists evaluate to True in a boolean context.
As to the "list comprehension is always better" point: no it's not. The equivalent list comprehension is:
[x and y for x, y in zip(X, Y)]
Which has to build an intermediate object (either list or generator, depending on the python version), and still requires the reader to know what zip does, just as much as map does. It's also likely to be slightly slower (because map + builtin function is fast - it all happens in the C layer, essentially). In fact, timeit shows that izip is faster (see below), but I really think the readability point is more important; you may also see different results if performance really matters.
>>> timeit.timeit('map(operator.and_, X,Y)', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
1.0160579681396484
>>> timeit.timeit('[x and y for x, y in zip(X, Y)]', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
1.3570780754089355
>>> timeit.timeit('[x and y for x, y in itertools.izip(X, Y)]', 'import operator; import itertools; import random; X = [random.choice([True,False]) for _ in range(1000)]; Y = [random.choice([True,False]) for _ in range(1000)]', number=10000)
0.965054988861084
That said, if you need arbitrary numbers of lists, you need to use all in a list comprehension (or combined with izip directly); and and_ is technically bitwise and, so be aware that might have funky results if working with numeric types other than bool.
Here is an all version:
import itertools
map(all,itertools.izip(X,Y,Z))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With