Why this doesn't work
The short version is that numpy's implementation of array.__contains__()
seems to be broken. The in
operator in python calls __contains__()
behind the scenes.
Meaning that a in b
is equivalent to b.__contains__(a)
.
I've loaded up your arrays in a REPL and try the following:
>>> b[:,0]
array([(0, 0), (1, 0), (2, 0)], dtype=object)
>>> (0,0) in b[:,0] # we expect it to be true
False
>>> (0,0) in list(b[:,0]) # this shouldn't be different from the above but it is
True
>>>
How to fix it
I don't see how your list comprehension could work since a[x]
is a tuple and b[:,:]
is a 2D matrix so of course they're not equal. But I'm assuming you meant to use in
instead of ==
. Do correct me if I'm wrong here and you meant something different that I'm just not seeing.
The first step is to convert b
from a 2D array to a 1D array so we can sift through it linearly and convert it to a list to avoid numpy's broken array.__contains()
like so:
bb = list(b.reshape(b.size))
Or, better yet, make it a set
since tuples are immutable and checking for in
in a set is O(1) instead of the list's O(n) behavior
>>> bb = set(b.reshape(b.size))
>>> print bb
set([(0, 1), (1, 2), (0, 0), (2, 1), (1, 1), (2, 0), (2, 2), (1, 0), (0, 2)])
>>>
Next we simply use the list comprehension to derive the table of booleans
>>> truth_table = [tuple(aa) in bb for aa in a]
>>> print truth_table
[True, True, True]
>>>
Full code:
def contained(a,b):
bb = set(b.flatten())
return [tuple(aa) in bb for aa in a]