如何获取未被另一个数组包含的子数组?(Python/Numpy)
Python数组(含Numpy)求子数组差集的解决方案
普通Python列表方案
由于列表不可哈希,无法直接用集合操作,我们可以先将子数组转为可哈希的元组,利用集合的差集特性实现:
first = [[0,10],[0,11],[0,12],[0,13]] second = [[0,10],[0,11]] def difference(arr1, arr2): # 将子数组转为元组存入集合 set_arr1 = set(tuple(sub) for sub in arr1) set_arr2 = set(tuple(sub) for sub in arr2) # 求差集后转回列表 return [list(sub_tuple) for sub_tuple in set_arr1 - set_arr2] print(difference(first, second)) # 输出: [[0, 12], [0, 13]]
Numpy数组方案
方法1:结构化数组转换
通过将二维数组转为结构化数组,让每个子数组成为一个可被np.setdiff1d识别的元素:
import numpy as np first_np = np.array([[0,10],[0,11],[0,12],[0,13]]) second_np = np.array([[0,10],[0,11]]) # 将二维数组转为结构化数组(每个子数组视为一个复合元素) first_struct = first_np.view('i,i').reshape(-1) second_struct = second_np.view('i,i').reshape(-1) # 计算差集后转回原二维格式 diff_struct = np.setdiff1d(first_struct, second_struct) diff_result = diff_struct.view('i').reshape(-1, 2) print(diff_result) # 输出: # [[ 0 12] # [ 0 13]]
注:
'i,i'表示每个元素由两个int类型组成,若你的子数组元素是其他类型(如float),需对应修改格式字符串(比如'f,f')。
方法2:广播比较筛选
利用Numpy的广播特性,逐行判断是否存在于第二个数组中:
import numpy as np first_np = np.array([[0,10],[0,11],[0,12],[0,13]]) second_np = np.array([[0,10],[0,11]]) # 广播比较每行是否与second中的某行完全匹配 match_mask = np.any((first_np[:, None] == second_np).all(axis=2), axis=1) # 取反得到不在second中的行的掩码 diff_result = first_np[~match_mask] print(diff_result) # 输出: # [[ 0 12] # [ 0 13]]
原有方法失效原因
np.setdiff1d会自动扁平化输入数组,因此返回的是单个元素的差集,而非子数组级别的差集。- 循环删除的方法中,
diff == equal是逐元素比较,返回的是布尔数组,np.where获取的是所有匹配元素的索引,而非整行的索引,导致删除操作破坏了数组结构。
内容的提问来源于stack exchange,提问作者BSDash
相关产品推荐
相关产品推荐

