用于集合

时间:2015-10-03 22:22:34

标签: python python-2.7 hash set

我正在尝试为问题实施基于集合的解决方案,并且遇到了一些问题。

问题是:我有两组Group个对象。这些集在email上应该是唯一的(因此我们可以检查一个集合中的对象是否为in另一个集合。)

但是,如果两个Group对象只有电子邮件匹配,则它们不是__eq__()(例如,一个集合可能包含具有新Group的更新description对象})。我的目标是设置一个集合,我只能根据email字段执行集合操作(​​交集和差异)...然后根据其他字段(descriptionname检查相等性)

    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)

1 个答案:

答案 0 :(得分:1)

Python的set类型使用对象的__eq__方法实现的相等性测试来确定对象是否与其内容中的另一个对象“相同”。 __hash__方法仅允许它更有效地查找要比较的其他元素。因此,您希望基于与__hash__方法不同的属性集使用__eq__方法是行不通的。具有相同__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的值,只要同一封电子邮件出现在同一个电子邮件中,两者都是关键。如果您希望它以其他方式工作,只需切换字典名称。