计算中的一个常见问题是找出列表是否包含重复条目。
探索解决问题的各种方法也是一个很好的主题。在这种情况下,我们将看到该问题的微不足道解决方案与改进解决方案之间的性能差异。
在Python列表中查找重复项
解决此问题的微不足道方法是扫描列表的每个元素与列表中的其他每个元素。毫无疑问,这将返回正确的答案,并在合理的时间范围内用于小列表,但是随着列表的增加,它将很快放慢速度。
def check_duplicate_trivial(项目):对于IDX范围(LEN(项目)):对于内部范围(LEN(项目)):如果Inner == IDX:继续#不要与自己比较如果项目[INNER] ==项目[IDX]:返回true返回false
这是一个循环中的循环 - 外循环是我们要比较的项目的索引,所有其他项目均使用内部循环进行索引。您可以看到,这种微不足道的实现对大列表确实不利 - 它可以使项目比较数量。
我们可以稍微改善该方法,而不是完全扫描列表。如果该函数找到了重复,则在此点通过返回结束。在大多数情况下,这将大大更快,在最糟糕的情况下,它仍将将每个元素与其他所有元素进行比较。
改进的实施:检查现有列表
那么,我们如何对此进行改进,并解决比较数量的问题是项目数量的平方?
对此的改进是保留已经看到的独特项目的第二个列表,然后检查该列表以查看该项目是否已经存在。
DEF CHECK_DUPLICATE_IMPREVED(项目):已经_seen = {}对于项目中的项目:如果已经在_seen中的项目:返回true已经_seen [item] = 0返回false
这意味着我们只扫描一次主列表。我们确实扫描了主列表中每个条目的唯一项目列表,但即使在最坏的情况下,这也大大减少了比较数量。
最快的实现:使用集合查找
这两个示例让我们检查是否有重复。改进的算法比微不足道的算法快得多,但是经过很多比较,它仍然相当慢。如果给出了大列表,仍然需要花费大量时间来完成。
Pythonic系统是否为此特定目的构建了一些东西,以便我们避免所有这些比较?
是的,我们可以使用所谓的集合。
使用哈希表备份集合。这将计算要添加的对象的哈希值,并将其用作添加对象时存储的键。对象可以具有相同的哈希值,并且在较大的集合中,使用哈希算法来平衡对象与可用哈希相平衡以保持性能一致。
可以将哈希视为指针或直接引用基础数据结构,这使查找非常快 - 通常,设置查找是一个操作。这就是将搜索项目问题转变为持续时间问题的绝佳选择。
def check_duplicate_set(项目):hash_bucket = set()对于项目中的项目:如果hash_bucket中的项目:返回truehash_bucket.add(项目)返回false
如您在上面的代码中看到的那样,我们在添加之前检查项目是否在集合中,如果是返回,我们现在将重复项的支票减少到了原始项目的单个扫描。
此功能也可以简化为一条线。为此,请从原始项目创建一个集合(一组仅具有唯一条目),并比较两者的大小:
def check_duplicate_distinct(项目):返回len(项目)!= len(set(items))
该代码既紧凑又有效。在Python,对于大多数要检测重复的情况,该集合是最佳性能使用方法。