元素可交换二维数组的去重方法

本文探讨了如何处理包含可交换元素的二维数组的去重问题。在数组中,元素对(a, b)和(b, a)被视为等价,但不允许存在(a, b)和(a, c)同时存在的情况。提出的解决方案首先通过交换元素顺序找出重复项,然后按元素的较小值排序,删除重复对子中的一个,以确保单射特性。这种方法适用于二维数组,且假设第一列到第二列的映射是单射的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

 本文想要解决以下问题:存在一数组X={x1,x2,x3...}X=\{x_1,x_2,x_3...\}X={x1,x2,x3...},其中每一个成员都包含了两个元素即xi∈R2x_i\in R^2xiR2,举个例子,二维平面的一个动点的运动轨迹就是这样一个数组,x,yx,yx,y坐标构成其成员。同时xix_ixi中的两个元素是可交换的(commutable),即(a,b)⇔(b,a)(a,b)\Leftrightarrow (b,a)(a,b)(b,a),想要从X中清除可能存在的重复元素,此时若xi和xjx_i和x_jxixj重复,那么有两种情况:

  1. xi=(a,b),xj=(a,b)x_i=(a,b),x_j=(a,b)xi=(a,b),xj=(a,b)
  2. xi=(b,a),xi=(a,b)x_i=(b,a),x_i=(a,b)xi=(b,a),xi=(a,b)
    此时就不再能用简单的unique()unique()unique()等方法来去重了,因为此类方法并未考虑可交换的情况,而是简单去除重复情形1,对重复情形2束手无策。本文考虑在附加约束:XXX中第一列到第二列为单射,即若含有成员(a,b)(a,b)(a,b)则必不含有(a,c)(a,c)(a,c)情况下的可交换二维数组去重方法。

解决方案

 总体思路也比较简单,首先通过对元素进行交换,确定出数组存在哪些重复成员,然后删除其中的一个即可。

提取重复元素

使用python中的set类型,set为无序集合,有集合的所有操作性质如取交集、并集等等,将二维矩阵定义为set类型得到集合S1S_1S1,交换X中每个元素内标量的顺序在定义为set类型得到集合S2S_2S2,取S1,S2S_1,S_2S1,S2的交集即得到了重复元素
代码:

x=np.array([[1,3],[5,9],[3,11],[2,7],[10,12],[11,3],[4,6],[6,4],[7,2],[8,11]])
s1=set(tuple([x[i,0],x[i,1]]) for i in range(x.shape[0]))
s2=set(tuple([x[i,1],x[i,0]]) for i in range(x.shape[0]))
bond=s1&s2

结果:

s1
Out[10]: {(1, 3),(2, 7),(3, 11),(4, 6),(5, 9),(6, 4),(7, 2),(8, 11),(10, 12), (11, 3)}
bond
Out[11]: {(2, 7), (3, 11), (4, 6), (6, 4), (7, 2), (11, 3)}

删除重复元素

 得到重复元素之后,每个重复元素都可组成形如(a,b),(b,a)(a,b),(b,a)(a,b),(b,a)的对子,因此我们不能直接用原始集合减去重复元素集合,否则会失去这些数据,而是应该删去对子中的任意一个以达到去重的目的。删去重复元素方法如下:
 首先,我们对重复元素数据进行排序,排序的依据为数组中每个二维元素的较小值,代码及结果如下:

temp_inter=[]
for i in bond:
    temp_inter.append(i)
temp_inter=np.array(temp_inter)
temp_inter=temp_inter[temp_inter.min(axis=1).argsort()]

结果:

array([[ 2,  7],
       [ 7,  2],
       [11,  3],
       [ 3, 11],
       [ 6,  4],
       [ 4,  6]])

可以看出通过上述操作就可以很轻易的将重复的成员放到相邻的位置,此时奇偶位置的元素即构成了一组对子,通过slice操作即可取出重复元素对子中的一个,代码及结果如下:

temp_inter=temp_inter[::2,:]

结果:

array([[ 2,  7],
       [11,  3],
       [ 6,  4]])

整体代码如下:

x=np.array([[1,3],[5,9],[3,11],[2,7],[10,12],[11,3],[4,6],[6,4],[7,2],[8,11]])
s1=set(tuple([x[i,0],x[i,1]]) for i in range(x.shape[0]))
s2=set(tuple([x[i,1],x[i,0]]) for i in range(x.shape[0]))
bond=s1&s2
temp_inter=[]
for i in bond:
    temp_inter.append(i)
temp_inter=np.array(temp_inter)
temp_inter=temp_inter[temp_inter.min(axis=1).argsort()]
temp_inter=temp_inter[::2,:]
temp_inter=set(tuple([temp_inter[i,0],temp_inter[i,1]]) for i in range(temp_inter.shape[0]))
s1=s1-temp_inter

总结

 值得注意的是,这种去重方法存在着局限性,隐含的条件是
如果将二维矩阵的第一列视为自变量,第二列视为因变量,则其中的映射应当是单射的,即虽然存在着xi=(a,b)⇔xj=(b,a)x_i=(a,b)\Leftrightarrow x_j=(b,a)xi=(a,b)xj=(b,a)这种重复元素,但不应存在xi=(a,b)⇔xj=(b,a),xi′=(a,c)⇔xj′=(c,a)x_i=(a,b)\Leftrightarrow x_j=(b,a),x'_i=(a,c)\Leftrightarrow x'_j=(c,a)xi=(a,b)xj=(b,a),xi=(a,c)xj=(c,a),否则使用使用上述代码就可能出现问题,举例如下:

重复元素:(2,4),(2,3),(3,2),(4,2)
排序后排布:(2,4),(2,3),(4,2),(3,2)
提取出重复元素:(2,3),(3,2)

 改方案通过一定的改进也可以适用于更高维的场景,其思路是一样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值