In [3]: arr1 = np.array([
...: [1, 2, 3, 4],
...: [2, 3, 1, 4],
...: [2, 4, 1, 5],
...: ])
...:
...: arr2 = np.array([
...: [2, 4, 1, 5],
...: [2, 1, 3, 5],
...: [1, 2, 3, 4],
...: ])
broadcasted equality followed by the appropriate mix of all
and any
:
In [8]: (arr1[:,None,:]==arr2[None,:,:]).shape
Out[8]: (3, 3, 4)
In [9]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2)
Out[9]:
array([[False, False, True],
[False, False, False],
[ True, False, False]])
In [10]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=0)
Out[10]: array([ True, False, True])
In [12]: arr1[_]
Out[12]:
array([[1, 2, 3, 4],
[2, 4, 1, 5]])
With sets
In [19]: set([tuple(row) for row in arr1])
Out[19]: {(1, 2, 3, 4), (2, 3, 1, 4), (2, 4, 1, 5)}
In [20]: set([tuple(row) for row in arr2])
Out[20]: {(1, 2, 3, 4), (2, 1, 3, 5), (2, 4, 1, 5)}
In [21]: _19.intersection(_20)
Out[21]: {(1, 2, 3, 4), (2, 4, 1, 5)}
===
If I expand arr2
to 4 rows:
...: arr2 = np.array([
...: [2, 4, 1, 5],
...: [2, 1, 3, 5],
...: [1, 2, 3, 4],
...: [1, 1, 1, 1],
...: ])
In [34]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=0)
Out[34]: array([ True, False, True, False])
any
on 0 produces a 4 element array, which has to be used to index arr2
(not arr1
as I originally did):
In [35]: arr2[_]
Out[35]:
array([[2, 4, 1, 5],
[1, 2, 3, 4]])
Or any
along the other axis:
In [36]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2).any(axis=1)
Out[36]: array([ True, False, True])
In [37]: arr1[_]
Out[37]:
array([[1, 2, 3, 4],
[2, 4, 1, 5]])
The all
produces (in this case) a (3,4) array:
In [38]: (arr1[:,None,:]==arr2[None,:,:]).all(axis=2)
Out[38]:
array([[False, False, True, False],
[False, False, False, False],
[ True, False, False, False]])
any
can reduce either rows or columns.