字典中数组的Python交集

Posted

技术标签:

【中文标题】字典中数组的Python交集【英文标题】:Python intersection of arrays in dictionary 【发布时间】:2020-04-03 19:03:58 【问题描述】:

我有数组字典,如下所示:

y_dict= 1: np.array([5, 124, 169, 111, 122, 184]),
         2: np.array([1, 2, 3, 4, 5, 6, 111, 184]), 
         3: np.array([169, 5, 111, 152]), 
         4: np.array([0, 567, 5, 78, 90, 111]),
         5: np.array([]),
         6: np.array([])

我需要在我的字典中找到拦截数组:y_dict。 作为第一步,我从空数组中清除了字典,就像

dic = i:j for i,j in y_dict.items() if np.array(j).size != 0

所以,dic 有以下观点:

dic =  1: np.array([5, 124, 169, 111, 122, 184]),
        2: np.array([1, 2, 3, 4, 5, 6, 111, 184]), 
        3: np.array([169, 5, 111, 152]), 
        4: np.array([0, 567, 5, 78, 90, 111])

为了找到拦截,我尝试使用元组方法:

result_dic = list(set.intersection(*(tuple(p) for p in v for v in dic.values())))

实际结果为空列表:[];

预期结果应该是:[5, 111]

你能帮我在字典中找到数组的交集吗?谢谢

【问题讨论】:

【参考方案1】:

您发布的代码过于复杂且错误,因为需要进行一次额外的内部迭代。你想做的事:

result_dic = list(set.intersection(*(set(v) for v in dic.values())))

或者使用map 并且没有for 循环:

result_dic = list(set.intersection(*(map(set,dic.values()))))

结果

[5, 111]
迭代值(忽略键) 将每个 numpy 数组转换为 set(转换为 tuple 也可以,但 intersection 无论如何都会将它们转换为集合) 通过参数解包将批次传递给intersection

我们甚至可以通过在每个数组上创建集合并使用 filter 过滤掉空的集合来摆脱第 1 步:

result_dic = list(set.intersection(*(filter(None,map(set,y_dict.values())))))

这是为了单线,但在现实生活中,表达式可能会被分解,因此它们更具可读性和可评论性​​。这种分解还可以帮助我们避免在不传递参数时发生的崩溃(因为没有非空集合),这会破坏与集合相交的智能方法(首先在Best way to find the intersection of multiple sets? 中描述)。

只需预先创建列表,只有当列表不为空时才调用交集。如果为空,只需创建一个空集:

non_empty_sets = [set(x) for x in y_dict.values() if x.size]
result_dic = list(set.intersection(*non_empty_sets)) if non_empty_sets else set()

【讨论】:

非常感谢您的解释 :) 我尝试使用没有提到 step1 的最后一个解决方案从 dict 中删除空数组并收到问题 unhashable type: 'numpy.ndarray'。我不明白为什么会这样?你知道为什么会这样吗? 我认为您的真实数据与显示的不同。也许你有二维数组?因为将 numpy 数组转换为集合会迭代数组的元素。如果元素是可散列的(就像整数一样)它可以工作,否则它不会。 for dict 里面有超过 20 个数组出现奇怪的错误:descriptor 'intersection' of 'set' object needs an argument :-( 您需要创建另一个问题,并为此创建一个minimal reproducible example【参考方案2】:

您应该在这里使用 numpy 的交集,而不是直接在 Python 中。并且您需要为空的交叉点添加特殊处理。

>>> intersection = None
>>> for a in y_dict.values(): 
...     if a.size: 
...         if intersection is None: 
...             intersection = a 
...             continue 
...         intersection = np.intersect1d(intersection, a) 
...
>>> if intersection is not None: 
...     print(intersection)
...
[  5 111]

对于intersection is None 的情况,这意味着y_dict 中的所有数组的大小为零(没有元素)。在这种情况下,交集没有明确定义,您必须自己决定代码应该在这里做什么 - 可能会引发异常,但这取决于用例。

【讨论】:

以上是关于字典中数组的Python交集的主要内容,如果未能解决你的问题,请参考以下文章

Python计算两个numpy数组的交集(Intersection)实战:两个输入数组的交集并排序获取交集元素及其索引如果输入数组不是一维的,它们将被展平(flatten),然后计算交集

Leetcode练习(Python):第350题:两个数组的交集 II:给定两个数组,编写一个函数来计算它们的交集。

Leetcode练习(Python):第350题:两个数组的交集 II:给定两个数组,编写一个函数来计算它们的交集。

Python中多个词典和列表字典的高效快速数据存储和处理,以及列表的两个词典的交集

字典键的交集是啥

LeetCode:350. 两个数组的交集 II(python,JavaScript)