Python | 删除数组中的镜像对

Com*_*ner 2 python arrays numpy

在python中,我有一个形状为n*2的数组(其中n是一个正整数).从本质上讲,这是一对数组.我希望删除此阵列中的所有镜像对.例如,以下阵列A 的形状为10*2.所述双[0,55][55,0]将构成一个这样的反射镜对中A,和我想保留一个出这两个的.

A = np.array([[ 0, 55], [ 5, 25], [12, 62], [27,  32], [25, 73], 
              [55, 0], [25, 5], [62, 12], [32, 27], [99, 95]])
Run Code Online (Sandbox Code Playgroud)

对于前面提到的示例,我希望结果数组看起来像:

B = np.array([[ 0, 55], [ 5, 25], [12, 62], [27,  32], [25, 73], [99,95])
Run Code Online (Sandbox Code Playgroud)

因为有6对独特的对(不包括4对镜像对).

我意识到我可以使用两个嵌套的for循环来实现这一点,但我希望使用最快的方法实现这一点,因为对于手头的实际问题,我将处理大型数组.我会很感激能得到一些帮助.

War*_*ser 6

一个神秘的单线:

In [301]: A
Out[301]: 
array([[ 0, 55],
       [ 5, 25],
       [12, 62],
       [27, 32],
       [25, 73],
       [55,  0],
       [25,  5],
       [62, 12],
       [32, 27],
       [99, 95]])

In [302]: np.unique(np.sort(A, axis=1).view(','.join([A.dtype.char]*2))).view(A.dtype).reshape(-1, 2)
Out[302]: 
array([[ 0, 55],
       [ 5, 25],
       [12, 62],
       [25, 73],
       [27, 32],
       [95, 99]])
Run Code Online (Sandbox Code Playgroud)

把它分解成几步......

首先,创建一个沿第二个轴排序的副本.在排序数组中,我们要删除重复的行.

In [303]: a = np.sort(A, axis=1)

In [304]: a
Out[304]: 
array([[ 0, 55],
       [ 5, 25],
       [12, 62],
       [27, 32],
       [25, 73],
       [ 0, 55],
       [ 5, 25],
       [12, 62],
       [27, 32],
       [95, 99]])
Run Code Online (Sandbox Code Playgroud)

numpy.unique()可用于查找数组的唯一元素,但它仅适用于一维数据.因此,我们将创建一个一维视图,b其中每行成为具有两个字段的单个结构.定义我们想要的新数据类型的一种方法是作为字符串:

In [305]: dt = ','.join([A.dtype.char]*2)

In [306]: dt
Out[306]: 'l,l'
Run Code Online (Sandbox Code Playgroud)

b是一个结构化的数组; 它是一维视图a:

In [307]: b = a.view(dt)

In [308]: b
Out[308]: 
array([[( 0, 55)],
       [( 5, 25)],
       [(12, 62)],
       [(27, 32)],
       [(25, 73)],
       [( 0, 55)],
       [( 5, 25)],
       [(12, 62)],
       [(27, 32)],
       [(95, 99)]], 
      dtype=[('f0', '<i8'), ('f1', '<i8')])
Run Code Online (Sandbox Code Playgroud)

现在我们numpy.unique()用来找到以下独特元素b:

In [309]: u = np.unique(b)

In [310]: u
Out[310]: 
array([( 0, 55), ( 5, 25), (12, 62), (25, 73), (27, 32), (95, 99)], 
      dtype=[('f0', '<i8'), ('f1', '<i8')])
Run Code Online (Sandbox Code Playgroud)

接下来,u使用原始数组的数据类型创建视图A.这将是一维的:

In [311]: v = u.view(A.dtype)

In [312]: v
Out[312]: array([ 0, 55,  5, 25, 12, 62, 25, 73, 27, 32, 95, 99])
Run Code Online (Sandbox Code Playgroud)

最后,重塑v以恢复二维数组:

In [313]: w = v.reshape(-1, 2)

In [314]: w
Out[314]: 
array([[ 0, 55],
       [ 5, 25],
       [12, 62],
       [25, 73],
       [27, 32],
       [95, 99]])
Run Code Online (Sandbox Code Playgroud)