Python 移除列表中重复的元素(长文讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 Python 编程中,列表(List)是一种常用的数据结构,它允许存储多个元素,并且支持动态修改。但在实际开发中,我们经常需要处理包含重复元素的列表,例如从用户输入、文件读取或 API 响应中获取的数据。如何高效地移除 Python 列表中重复的元素,同时保留原始顺序或特定逻辑,是开发者需要掌握的基础技能。本文将从原理、方法、性能对比到实际案例,系统性地讲解这一主题,帮助读者在不同场景下灵活应对。


一、基础概念:为什么需要去重?

列表中重复元素的存在,可能导致数据冗余、计算错误或逻辑混乱。例如,假设我们有一个记录用户每日访问路径的列表:

user_paths = [  
    "/home", "/about", "/home", "/contact", "/home", "/blog"  
]  

若直接对这些路径进行统计或分析,重复的 "/home" 会误导结果。因此,移除重复元素的首要目标是简化数据,确保后续处理的准确性。


二、基础方法:循环与集合

1. 使用循环逐项判断

对于编程新手,最直观的方法是通过循环遍历列表,并逐项检查是否已存在临时列表中:

def remove_duplicates_loop(input_list):  
    unique_list = []  
    for item in input_list:  
        if item not in unique_list:  
            unique_list.append(item)  
    return unique_list  

original = [1, 2, 2, 3, 4, 4, 4]  
print(remove_duplicates_loop(original))  # 输出: [1, 2, 3, 4]  

原理比喻:这就像整理书架,每次取一本书时先检查书架上是否有同名书籍,没有则放入。这种方法简单直观,但效率较低,尤其是当列表较大时。

2. 利用集合(Set)的无重复特性

集合是 Python 中一种不允许重复元素的数据结构。将列表转换为集合后,再转回列表,即可快速去重:

original = ["apple", "banana", "apple", "orange"]  
unique = list(set(original))  
print(unique)  # 输出顺序可能无规律,例如:['orange', 'banana', 'apple']  

注意:集合不保留元素的原始顺序。如果需要保持顺序,可以结合循环与集合实现:

def ordered_set(input_list):  
    seen = set()  
    result = []  
    for item in input_list:  
        if item not in seen:  
            seen.add(item)  
            result.append(item)  
    return result  

print(ordered_set(original))  # 输出: ['apple', 'banana', 'orange']  

性能对比:集合方法的时间复杂度为 O(n),比纯循环的 O(n²) 更高效,但需注意顺序问题。


三、高级技巧:列表推导式与字典

1. 列表推导式优化循环

通过列表推导式(List Comprehension)可以简化代码逻辑:

def remove_duplicates_comprehension(input_list):  
    seen = set()  
    return [x for x in input_list if not (x in seen or seen.add(x))]  

print(remove_duplicates_comprehension([5, 3, 5, 2, 3]))  # 输出: [5, 3, 2]  

原理:列表推导式内部维护了一个 seen 集合,通过条件表达式判断元素是否已存在。

2. 字典的键唯一性

Python 3.7+ 中,字典的插入顺序是稳定的。利用字典的键唯一性特性,可以实现保留顺序的去重

def dict_method(input_list):  
    return list(dict.fromkeys(input_list))  

print(dict_method(["a", "b", "a", "c", "b"]))  # 输出: ['a', 'b', 'c']  

原理:字典的 fromkeys() 方法会以列表元素作为键,自动过滤重复项,并按插入顺序排列。


四、特殊场景:处理嵌套结构或对象

1. 嵌套列表的去重

若列表元素是可变对象(如字典或列表),需先将其转换为可哈希类型(如元组),再结合集合处理:

nested_list = [[1, 2], [3, 4], [1, 2], [5, 6]]  
unique_tuples = set(tuple(item) for item in nested_list)  
unique_list = [list(t) for t in unique_tuples]  
print(unique_list)  # 输出顺序可能无规律  

2. 自定义对象的去重

对于自定义类的实例,需重写 __hash__()__eq__() 方法,以定义对象的唯一性条件:

class Person:  
    def __init__(self, name, age):  
        self.name = name  
        self.age = age  

    def __hash__(self):  
        return hash((self.name, self.age))  

    def __eq__(self, other):  
        return isinstance(other, Person) and (  
            self.name == other.name and self.age == other.age  
        )  

people = [  
    Person("Alice", 30),  
    Person("Bob", 25),  
    Person("Alice", 30)  # 重复项  
]  
unique_people = list(set(people))  # 有效去重  

五、性能与选择指南

1. 时间与空间复杂度对比

方法时间复杂度空间复杂度是否保留顺序
循环遍历O(n²)O(n)
集合转换O(n)O(n)
集合+顺序维护O(n)O(n)
字典 fromkeys()O(n)O(n)

2. 场景选择建议

  • 简单列表且无需顺序:直接使用 set() 转换。
  • 需要保留顺序:优先选择 dict.fromkeys() 或集合+循环方法。
  • 处理大型数据集:避免 O(n²) 的循环,改用集合或字典优化。

六、常见误区与注意事项

1. 原始列表未被修改

所有去重方法默认返回新列表,原始列表不会被修改。例如:

original = [1, 1, 2]  
new_list = list(set(original))  
print(original)  # 输出: [1, 1, 2]  

若需直接修改原列表,可用 [:] 赋值:

original[:] = list(set(original))  

2. 元素类型与可哈希性

集合和字典要求元素是可哈希的(如整数、字符串、元组),若列表包含列表或字典等不可哈希类型,需先转换为元组或冻结字典。

3. 多条件去重

若需根据部分属性去重(如仅比较对象的 name 属性),需自定义逻辑:

class Product:  
    def __init__(self, name, price):  
        self.name = name  
        self.price = price  

products = [  
    Product("Apple", 1.0),  
    Product("Apple", 1.5),  # 同名不同价  
    Product("Banana", 0.5)  
]  

seen_names = set()  
unique_products = []  
for p in products:  
    if p.name not in seen_names:  
        seen_names.add(p.name)  
        unique_products.append(p)  

七、实际案例:数据分析中的去重应用

假设我们从 CSV 文件中读取用户行为日志,其中包含重复的点击记录:

import csv  

raw_data = [  
    {"user": "u1", "page": "/home"},  
    {"user": "u1", "page": "/home"},  # 重复项  
    {"user": "u2", "page": "/about"}  
]  

unique_events = []  
seen = set()  
for event in raw_data:  
    key = (event["user"], event["page"])  # 定义唯一键  
    if key not in seen:  
        seen.add(key)  
        unique_events.append(event)  

此方法通过组合键(userpage)确保去重逻辑的灵活性。


八、结论

移除 Python 列表中重复的元素是数据清洗和预处理的基础操作。本文通过循序渐进的方式,从基础循环到高级技巧,结合性能分析和实际案例,帮助读者理解不同方法的适用场景与实现细节。在实际开发中,开发者需根据数据规模、元素类型和顺序要求,灵活选择最优方案。随着对 Python 内置数据结构(如集合、字典)的深入掌握,这一看似简单的任务也能展现出强大的灵活性与效率。

最新发布