在集合中使用不同的 __hash__ 和 __eq__ 方法
Different __hash__ and __eq__ methods for use in set
我正在尝试为一个问题实施基于集合的解决方案,并且已经 运行 解决了一些问题。
问题是:我有 2 组 Group
对象。这些集合在 email
上应该是唯一的(因此我们可以检查一组中的对象是否是另一组中的对象 in
)。
但是,如果两个 Group
对象只有一个电子邮件匹配(例如,一个集合可能包含一个更新的 Group
对象,并且有一个新的 description
).目标是有一个集合,我可以在其中仅基于 email
字段执行集合操作(交集和差集)...然后根据其他字段(description
和 name
检查相等性)
class Group:
def __init__(self, name, email, description):
self.name = name
self.email = email
self.description = description
def __hash__(self):
return hash(self.email)
def __eq__(self, other):
return self.email == other.email
and self.description == other.description
and self.name == other.name
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
return "Description: {0} Email: {1} Name: {2}".format(self.description, self.email, self.name)
所以我希望所有断言语句都在这里传递:
group_1 = Group('first test group', 'testing@example.com', 'example description')
group_2 = Group('second test group', 'real@example.com', 'example description')
group_3 = Group('third group', 'testing@example.com', 'example description')
group_5 = Group('updated name', 'testing@example.com', 'example description')
group_set = set([group_1, group_2, group_3])
group_set_2 = set([group_3, group_5])
self.assertTrue(group_5 in group_set.intersection(group_set_2))
self.assertEqual(2, len(group_set))
self.assertTrue(group_5 in group_set)
Python 的 set
类型使用对象的 __eq__
方法实现的相等性测试来确定对象是否 "the same" 作为其内容中的另一个对象。 __hash__
方法只允许它找到其他元素以更有效地进行比较。因此,您希望使用基于不同于 __eq__
方法的一组不同属性的 __hash__
方法是行不通的。具有相同 __hash__
值的多个不相等对象可以存在于同一个 set
中(尽管 set
由于散列冲突而效率稍低)。
如果您想要从电子邮件地址到 Group
的唯一映射,我建议使用字典,其中键是电子邮件地址,值是 Group
对象。这将让您确保电子邮件地址是唯一的,同时还让您以最合适的方式比较 Group
个对象。
要在两个这样的字典之间执行并集,请对一个字典的副本使用 update
方法:
union = dict_1.copy()
union.update(dict_2)
对于路口,使用字典理解:
intersection = {email: group for email, group in dict_2.iteritems() if email in dict_1}
这两个操作都将优先使用 dict_2
中的值而不是 dict_1
中的值,只要相同的电子邮件作为键出现在两者中。如果你想让它以另一种方式工作,只需切换字典名称即可。
我正在尝试为一个问题实施基于集合的解决方案,并且已经 运行 解决了一些问题。
问题是:我有 2 组 Group
对象。这些集合在 email
上应该是唯一的(因此我们可以检查一组中的对象是否是另一组中的对象 in
)。
但是,如果两个 Group
对象只有一个电子邮件匹配(例如,一个集合可能包含一个更新的 Group
对象,并且有一个新的 description
).目标是有一个集合,我可以在其中仅基于 email
字段执行集合操作(交集和差集)...然后根据其他字段(description
和 name
检查相等性)
class Group:
def __init__(self, name, email, description):
self.name = name
self.email = email
self.description = description
def __hash__(self):
return hash(self.email)
def __eq__(self, other):
return self.email == other.email
and self.description == other.description
and self.name == other.name
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
return "Description: {0} Email: {1} Name: {2}".format(self.description, self.email, self.name)
所以我希望所有断言语句都在这里传递:
group_1 = Group('first test group', 'testing@example.com', 'example description')
group_2 = Group('second test group', 'real@example.com', 'example description')
group_3 = Group('third group', 'testing@example.com', 'example description')
group_5 = Group('updated name', 'testing@example.com', 'example description')
group_set = set([group_1, group_2, group_3])
group_set_2 = set([group_3, group_5])
self.assertTrue(group_5 in group_set.intersection(group_set_2))
self.assertEqual(2, len(group_set))
self.assertTrue(group_5 in group_set)
Python 的 set
类型使用对象的 __eq__
方法实现的相等性测试来确定对象是否 "the same" 作为其内容中的另一个对象。 __hash__
方法只允许它找到其他元素以更有效地进行比较。因此,您希望使用基于不同于 __eq__
方法的一组不同属性的 __hash__
方法是行不通的。具有相同 __hash__
值的多个不相等对象可以存在于同一个 set
中(尽管 set
由于散列冲突而效率稍低)。
如果您想要从电子邮件地址到 Group
的唯一映射,我建议使用字典,其中键是电子邮件地址,值是 Group
对象。这将让您确保电子邮件地址是唯一的,同时还让您以最合适的方式比较 Group
个对象。
要在两个这样的字典之间执行并集,请对一个字典的副本使用 update
方法:
union = dict_1.copy()
union.update(dict_2)
对于路口,使用字典理解:
intersection = {email: group for email, group in dict_2.iteritems() if email in dict_1}
这两个操作都将优先使用 dict_2
中的值而不是 dict_1
中的值,只要相同的电子邮件作为键出现在两者中。如果你想让它以另一种方式工作,只需切换字典名称即可。