Reputation: 3052
I have 3 lists:
a = [True, False, True]
b = [False, False, True]
c = [True, True, False]
When I type
a or b or c
I want to get back a list that's
[True, True, True]
but I'm getting back
[True, False, True]
Any ideas on why? And how can I combine these masks?
Upvotes: 15
Views: 22789
Reputation: 1268
This is a good place to use one of python's asterisk functions (*args
, **kwargs
), which will allow you to pass 3 or 300000 lists.
a = [True, False, True]
b = [False, False, True]
c = [True, True, False]
data_lists = [a,b,c]
Here you use *
to expand that list as arguments, zip
to rearrange your data into columns (as lists), and any
to check if any cell in that column is True
.
[any(l) for l in zip(*data_lists)]
[True, True, True]
If you're working with a lot of lists it's the same, e.g.
import numpy as np
data_lists = [[True if (i == j) else False for i in range(7)] for j in range(7)]
np.matrix(data_lists)
matrix([[ True, False, False, False, False, False, False],
[False, True, False, False, False, False, False],
[False, False, True, False, False, False, False],
[False, False, False, True, False, False, False],
[False, False, False, False, True, False, False],
[False, False, False, False, False, True, False],
[False, False, False, False, False, False, True]])
[any(l) for l in zip(*data_lists)]
[True, True, True, True, True, True, True]
Upvotes: 1
Reputation: 21
Here is how to do it fast (large arrays) using numpy:
import numpy as np
a = [True, False, True,...]
b = [False, False, True,...]
c = [True, True, False,...]
res = (np.column_stack((a,b,c)).any(axis=1)
print res
Note that a
becomes the first column, b
the second, and so on when using np.column_stack()
. Then do a np.any()
(logical OR) on that array
along axis=1
which will compare the first elements of a
,b
, and c
, and so on, and so on; resulting in a boolean vector that is the same length as the vectors you want to compare.
Upvotes: 2
Reputation: 8400
How about this:
from numpy import asarray as ar
a = [True, False, True]
b = [False, False, True]
c = [True, True, False]
Try:
>>> ar(a) | ar(b) | ar(c) #note also the use `|` instead of `or`
array([ True, True, True], dtype=bool)
So no need for zip
etc.
Upvotes: 13
Reputation: 64002
Your or
operators are comparing the lists as entire objects, not their elements. Since a
is not an empty list, it evaluates as true, and becomes the result of the or
. b
and c
are not even evaluated.
To produce the logical OR of the three lists position-wise, you have to iterate over their contents and OR the values at each position. To convert a bunch of iterables into a list of their grouped elements, use zip()
. To check if any element in an iterable is true (the OR of its entire contents), use any()
. Do these two at once with a list comprehension:
mask = [any(tup) for tup in zip(a, b, c)]
Upvotes: 13
Reputation: 126837
or
returns the first operand if it evaluates as true, and a non-empty list evaluates as true
; so, a or b or c
will always return a
if it's a non-empty list.
Probably you want
[any(t) for t in zip(a, b, c)]
(this works also for element-wise and
if you replace any
with all
)
Upvotes: 7
Reputation: 34156
Try this:
a = [True, False, True]
b = [False, False, True]
c = [True, True, False]
res = [a[i] or b[i] or c[i] for i in range(len(a))]
print res
Upvotes: 2
Reputation: 369164
a
is treated as true because it contains values; b
, c
is not evaluated.
>>> bool([])
False
>>> bool([True])
True
>>> bool([False])
True
>>> [False] or [True]
[False]
According to Boolean Operations:
The expression
x or y
first evaluatesx
; ifx
is true, its value is returned; otherwise,y
is evaluated and the resulting value is returned.
Upvotes: 3