【问题标题】:How to efficiently remove duplicates from a python list based on equality, not hashes如何基于相等而不是哈希有效地从 python 列表中删除重复项
【发布时间】:2017-06-01 10:53:26
【问题描述】:

我们有一个类的实例列表。我们实际上想要一个Set,即没有重复元素的组。列表中相同的元素相等,但它们的哈希值不同,因为它们是单独实例化的。所以a==bTruea is bFalse

有没有办法将这个问题向量化或以其他方式使其高效。我们能想到的唯一解决方案涉及 for 循环,而且似乎有更有效的解决方案。

编辑:我认为它与 "Elegant ways to support equivalence" 不同,因为等效性很好,只是 Set 依赖于比较哈希。

编辑:for 循环解决方案类似于,对列表进行排序,然后迭代,如果当前值与最后一个值相同,则删除当前值

编辑:明确地说,我们不拥有这个类,我们只有它的实例。所以我们可以包装实例并实现一个更有用的散列函数,但是,这似乎可能与 for 循环方法几乎一样昂贵 - 虽然可能是错误的

编辑:对不起,如果感觉我在这里移动了一些球门柱 - 没有一个简单的 val 可以替换为哈希的对象,这种方法需要以某种方式生成 UID每个不同的实例。

【问题讨论】:

  • 是否可以以某种方式序列化状态,例如您可以将类转换为表示其状态的元组然后对其进行哈希处理吗?这些类是否具有可比性(即可排序)?
  • 是的,set 需要它的项目是可散列的,所以你只需要实现一个合适的__hash__ 方法。并确保您的对象不会发生变异!
  • "列表中相同的元素,但它们的哈希值不同" 你真的应该再考虑一下这个问题。哈希值是否有必要不同,或者您只是没有为实现__hash__ 而烦恼?相等和散列不一致会引发大量问题,您刚刚遇到的第一个问题。
  • 应该这样吗? > 循环将使用 O(n2) 来扫描整个列表,而通过哈希查找应该只需要 O(n) 在集合中。

标签: python


【解决方案1】:

也许这就是你需要的? 使散列成为类字段的函数。

这是一个简单的例子:

class A:
    def __init__(self, v):
        self.val = v

    def __eq__(self, other):
        return self.val == other.val

    def __hash__(self):
        return self.val

    def __repr__(self):
        return 'A(%s)' % self.val

a = set([A(2), A(3), A(4), A(2), A(10), A(4)])
print(a)
# {A(10), A(2), A(3), A(4)}

【讨论】:

    【解决方案2】:

    我假设您正在使用自己创建的类,并且您已经实现了自己的相等方法。

    确实,从Object 继承的默认哈希方法对于不同的实例返回不同的值。根据我的阅读,它要么基于 id(),要么是随机的,具体取决于 Python 版本。

    但是,您可以轻松实现自己的 __hash__ 方法来解决此问题。

    How to implement a good __hash__ function in python

    __hash__ 应该为相等的对象返回相同的值。它也不应该在对象的生命周期内改变;通常你只为不可变对象实现它。

    这可能不是您想要的答案,但它是一种干净且简单的方法。然后就可以正常创建Set了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-11
      • 1970-01-01
      • 2023-04-09
      • 2015-01-17
      • 1970-01-01
      • 2013-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多