2.1.2 删除列表中的重复元素并保持顺序不变

在Python程序中,我们可以删除列表中重复出现的元素,并且保持剩下元素的显示顺序不变。如果序列中保存的元素是可散列的(hashable),那么上述功能可以使用集合和生成器实现。例如,下面的文件delshun.py演示了在可散列情况下的实现过程。

源码路径:daima\第2章\delshun.py

def dedupe(items):
     seen = set()
     for item in items:
          if item not in seen:
                yield item
                seen.add(item)
if __name__ == '__main__':
     a = [5, 5, 2, 1, 9, 1, 5, 10]
     print(a)
     print(list(dedupe(a)))

如果一个对象是可散列的,那么在它的生存期内必须是不可变的,这需要有一个__hash__()方法。在Python程序中,整数、浮点数、字符串和元组都是不可变的。在上述代码中,函数dedupe()实现了可散列情况下的删除重复元素功能,并且保持剩下元素的显示顺序不变。执行结果如图2-4所示。

图2-4 执行结果

上述实例文件delshun.py有一个缺陷,只有当序列中的元素是可散列的时候才能这么做。如果想在不可散列的对象序列中去除重复项,并保持顺序不变,应该如何实现呢?下面的实例文件buhaxi.py演示了上述功能的实现过程。

源码路径:daima\第2章\num.py

def buha(items, key=None):
     seen = set()
     for item in items:
          val = item if key is None else key(item)
          if val not in seen:
               yield item
               seen.add(val)
if __name__ == '__main__':
     a = [
          {'x': 2, 'y': 3},
          {'x': 1, 'y': 4},
          {'x': 2, 'y': 3},
          {'x': 2, 'y': 3},
          {'x': 10, 'y': 15}
          ]
     print(a)
     print(list(buha(a, key=lambda a: (a['x'],a['y']))))

在上述代码中,函数buha()中的参数key的功能是将序列中的元素转换为可散列的类型,这样做的目的是检测重复选项。执行结果如图2-5所示。

图2-5 执行结果