Removing duplicates in lists
技术背景
在Python编程中,列表去重是一个常见的需求。当我们处理数据时,经常会遇到列表中存在重复元素的情况,为了后续数据处理的准确性和效率,需要将这些重复元素去除。同时,根据不同的业务场景,可能还需要保留元素的原始顺序。
实现步骤
不保留顺序
- 使用
set
:set
是Python中的一种无序集合,其中的元素是唯一的。可以将列表转换为set
,再转换回列表来实现去重。
1 2 3
| t = [1, 2, 3, 1, 2, 3, 5, 6, 7, 8] result = list(set(t)) print(result)
|
保留顺序
- 使用
OrderedDict
:从Python 3.7开始,内置字典保证按插入顺序排列。可以使用dict.fromkeys()
方法去重并保留顺序。
1 2 3 4
| from collections import OrderedDict t = [1, 2, 3, 1, 2, 3, 5, 6, 7, 8] result = list(dict.fromkeys(t)) print(result)
|
- 自定义循环:通过遍历列表,检查元素是否已存在于新列表中,若不存在则添加。
1 2 3 4 5 6
| t = [1, 2, 3, 1, 2, 3, 5, 6, 7, 8] s = [] for i in t: if i not in s: s.append(i) print(s)
|
核心代码
自定义类和函数实现去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| from collections import OrderedDict, Counter
class Container: def __init__(self, obj): self.obj = obj def __eq__(self, obj): return self.obj == obj def __hash__(self): try: return hash(self.obj) except: return id(self.obj)
class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered'
def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self): return self.__class__, (OrderedDict(self),)
def remd(sequence): cnt = Counter() for x in sequence: cnt[Container(x)] += 1 return [item.obj for item in cnt]
def oremd(sequence): cnt = OrderedCounter() for x in sequence: cnt[Container(x)] += 1 return [item.obj for item in cnt]
|
使用生成器去重
1 2 3 4 5 6 7 8 9
| def uniqify(iterable): seen = set() for item in iterable: if item not in seen: seen.add(item) yield item
unique_list = list(uniqify([1, 2, 3, 4, 3, 2, 4, 5, 6, 7, 6, 8, 8])) print(unique_list)
|
最佳实践
- 若不关心元素顺序,优先使用
set
方法,因为它简单且效率高。 - 若需要保留元素顺序,且使用Python 3.7及以上版本,推荐使用
dict.fromkeys()
方法,代码简洁且性能较好。 - 对于包含不可哈希元素的列表,可使用自定义类和函数的方式去重。
常见问题
元素顺序丢失
使用set
方法去重时,元素的原始顺序会丢失。若需要保留顺序,应使用OrderedDict
或自定义循环的方法。
不可哈希元素
若列表中包含不可哈希元素(如列表对象),set
和dict
方法会报错。此时可使用自定义类和函数,将不可哈希元素转换为可处理的形式。