进行设置差异时忽略最后一个元素的 Pythonic 方式

Gra*_*ex. 12 python set python-2.7

假设我有两个set()

a = {('1', '2', '3', 'a'), ('1', '2', '4', 'a'), ('1', '2', '5', 'b')}
b = {('1', '2', '3', 'b'), ('1', '2', '4', 'b'), ('1', '2', '6', 'b')}
Run Code Online (Sandbox Code Playgroud)

现在,我想要做的是找到集差b \ a但忽略每个元组中的最后一个元素。所以这就像做这样的事情:

a = {('1', '2', '3'), ('1', '2', '4'), ('1', '2', '5')}
b = {('1', '2', '3'), ('1', '2', '4'), ('1', '2', '6')}

In[1]: b - a
Out[1]: {('1', '2', '6')}
Run Code Online (Sandbox Code Playgroud)

预期输出:

b \ a = {('1', '2', '6', 'b')}

是否有任何明显的/pythonic 方法可以实现这一点,而无需手动迭代每个集合并检查每个集合tuple[:3]

Iza*_*gen 11

以下是您如何编写自己的类来覆盖元组的正常散列行为​​:

a_data = [('1', '2', '3', 'a'), ('1', '2', '4', 'a'), ('1', '2', '5', 'b')]
b_data = [('1', '2', '3', 'b'), ('1', '2', '4', 'b'), ('1', '2', '6', 'b')]

class HashableIgnoresLastElement(tuple):
    def __eq__(self, other):
        return self[:-1] == other[:-1]

    def __hash__(self):
        return hash(self[:-1])

a = set(map(HashableIgnoresLastElement, a_data))
b = set(map(HashableIgnoresLastElement, b_data))

print(b - a)
Run Code Online (Sandbox Code Playgroud)

带输出

{('1', '2', '6', 'b')}
Run Code Online (Sandbox Code Playgroud)

要修改元组集的行为方式,我们必须修改元组的散列方式。

这里

如果一个对象的哈希值在其生命周期内永远不会改变(它需要一个__hash__()方法),并且可以与其他对象进行比较(它需要一个方法),那么它就是可哈希的__eq__()。比较相等的可散列对象必须具有相同的散列值。

哈希能力使对象可用作字典键和集合成员,因为这些数据结构在内部使用哈希值。

因此,为了使散列忽略最后一个元素,我们不得不超负荷dunder方法__eq____hash__适当的。这最终并没有那么难,因为我们所要做的就是切掉最后一个元素,然后委托给普通tuple.

进一步阅读: