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