我尝试使用numpy的
intersect1d
来比较两个字典中的键。然而,由于与字典键是对象相关的某种原因,这总是返回零的交集。我想知道为什么这种行为在任何方面都是可取的。
d1 = {'a':1, 'b':2}
d2 = {'b':2, 'c':3}
np.intersect1d(d1.keys(), d2.keys())
> array([], dtype=object)
但是,
np.intersect1d(list(d1.keys()), list(d2.keys()))
> array(['b'], dtype='<U1')
这是预期行为吗?如果是,为什么?
字典键是特殊对象(类似集合),它们是字典键的动态视图(请参阅doc)。它们的行为确实“出乎意料”(例如,您不能像列表一样对它们进行切片:
d1.keys()[0]
)
np.intersect1d
在dict.keys()
上没有按预期工作,但为什么在这里使用numpy呢?该函数被定义为适用于数组,而不是任何对象。
此外,由于对象需要转换为数组,这比纯 python 慢。最好使用简单的
set
交叉点 set(d1) & set(d2)
:
d1 = dict.fromkeys(range(1, 1_000_000))
d2 = dict.fromkeys(range(1, 2_000_000, 2))
%timeit np.intersect1d(list(d1), list(d2))
# 565 ms ± 21.9 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%timeit set(d1) & set(d2)
# 225 ms ± 6.34 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
intersect1d()
的参数是
ar1, ar2array_like
Input arrays. Will be flattened if not already 1D.
参见https://numpy.org/doc/stable/reference/ generated/numpy.intersect1d.html。
dict.keys()
的返回值是字典视图objects,参见https://docs.python.org/3/library/stdtypes.html#dict-views。因此,numpy
将这些视图对象转换为对象数组,因为它们不是数字的集合:
>>> np.array({'a':1, 'b':2}.keys())
array(dict_keys(['a', 'b']), dtype=object)
现在
intersect1d()
将失败,因为这些输入数组每个都只有一个元素:第一个数组中的 dict_keys(['a', 'b'])
和第二个数组中的 dict_keys(['b', 'c'])
。这些是不同的对象,因此它们的交集是一个空集。