Python列表去重的核心思路是利用集合的唯一性或遍历记录元素。最高效方法是使用set,但不保留顺序;若需保留顺序,推荐collections.OrderedDict.fromkeys()或列表推导式结合辅助set,两者均高效且保持O(n)时间复杂度;对于不可哈希对象,可通过转换为元组或自定义__hash__和__eq__方法处理。

Python列表中删除重复项的核心思路,无非就是利用数据结构的特性(比如集合的唯一性),或者通过遍历并记录已出现过的元素来实现。最直接且高效的方法通常是借助Python内置的
set
set
collections.OrderedDict
说实话,每次遇到列表去重的问题,我脑子里首先跳出来的就是
set
方法一:利用 set
这是最Pythonic,也是我个人最喜欢的一种方法,尤其是在对元素顺序没有要求的时候。
set
set
立即学习“Python免费学习笔记(深入)”;
original_list = [1, 2, 2, 3, 4, 4, 5, 1] unique_elements = list(set(original_list)) print(unique_elements) # 输出可能是 [1, 2, 3, 4, 5] 或其他顺序
这个方法的优点是代码极其简洁,执行效率也相当高,尤其对于大型列表。但它有个明显的“副作用”:原始列表的顺序会丢失,因为
set
方法二:使用循环和辅助列表(保留顺序,但效率相对低)
这种方法更像是我们用“人脑”去重的方式:遍历一遍列表,看到一个元素,如果它之前没出现过,就把它加到新列表里。
original_list = [1, 2, 2, 3, 4, 4, 5, 1]
unique_elements = []
for item in original_list:
if item not in unique_elements:
unique_elements.append(item)
print(unique_elements) # 输出: [1, 2, 3, 4, 5]这种方法能完美保留元素的原始顺序。但效率上,当
original_list
item not in unique_elements
unique_elements
方法三:利用 collections.OrderedDict.fromkeys()
这是一个非常优雅且高效的解决方案,它结合了字典键的唯一性和
OrderedDict
OrderedDict.fromkeys(iterable)
iterable
None
OrderedDict
from collections import OrderedDict original_list = [1, 2, 2, 3, 4, 4, 5, 1] unique_elements = list(OrderedDict.fromkeys(original_list)) print(unique_elements) # 输出: [1, 2, 3, 4, 5]
我个人觉得这个方法非常巧妙,它在保证了顺序的同时,也保持了接近
set
方法四:使用列表推导式与辅助 set
这其实是方法二的优化版,用一个
set
unique_elements
original_list = [1, 2, 2, 3, 4, 4, 5, 1] seen = set() unique_elements = [item for item in original_list if item not in seen and not seen.add(item)] print(unique_elements) # 输出: [1, 2, 3, 4, 5]
这里
not seen.add(item)
set.add()
None
not None
True
item
seen
item not in seen
True
seen.add(item)
item
seen
not seen.add(item)
True
item
unique_elements
item
seen
item not in seen
False
item
要说“最快”,这其实得看具体情况和你的需求。但我们通常可以根据元素的数量级和是否需要保持顺序来做个大致的判断。
从理论上讲,基于哈希表(
set
dict
set()
list(set(your_list))
collections.OrderedDict.fromkeys()
set
列表推导式与辅助 set
set
OrderedDict.fromkeys()
循环遍历与 in
unique_elements
item not in unique_elements
unique_elements
总结一下我的看法:
list(set(your_list))
list(OrderedDict.fromkeys(your_list))
set
in
我通常会根据实际项目需求和列表规模来选择。如果不是性能瓶颈,我更倾向于代码的清晰和简洁。
这确实是个让人头疼的问题!当你的列表里装着一些“不听话”的家伙,比如其他列表、字典,或者自定义的、没有实现
__hash__
set()
OrderedDict.fromkeys()
TypeError: unhashable type: 'list'
面对这种场景,我们得换个思路,或者说,得“曲线救国”。
技巧一:手动遍历,并自定义“相等”判断
这是最通用但也最“笨拙”的方法,但它能处理一切情况。你需要自己定义什么是“重复”。
original_list_of_lists = [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4, 5]]
unique_elements = []
for item in original_list_of_lists:
# 这里的关键是判断 item 是否已存在于 unique_elements 中
# 对于列表,Python默认的 == 操作符会进行值比较
if item not in unique_elements:
unique_elements.append(item)
print(unique_elements) # 输出: [[1, 2], [3, 4], [5, 6], [3, 4, 5]]这种方法的核心在于
item not in unique_elements
__eq__
技巧二:将不可哈希对象转换为可哈希的“代理”形式
这是我个人觉得比较优雅且高效的解决方案,前提是你的不可哈希对象能被可靠地转换为可哈希的形式。
对于列表的列表(list of lists): 我们可以把内部的列表转换为元组(tuple),因为元组是不可变的,因此是可哈希的。
original_list_of_lists = [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4, 5]] # 将内部列表转换为元组,然后用set去重 # 这里用map很简洁,也可以用列表推导式 tuple_list = list(map(tuple, original_list_of_lists)) unique_tuples = list(set(tuple_list)) # 如果需要,再转回列表的列表 unique_elements = list(map(list, unique_tuples)) print(unique_elements) # 输出: [[1, 2], [3, 4], [5, 6], [3, 4, 5]] (顺序可能打乱)
如果需要保留顺序,可以结合
OrderedDict
from collections import OrderedDict original_list_of_lists = [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4, 5]] # 将内部列表转换为元组,然后用OrderedDict去重 unique_tuples_ordered = list(OrderedDict.fromkeys(map(tuple, original_list_of_lists))) unique_elements_ordered = list(map(list, unique_tuples_ordered)) print(unique_elements_ordered) # 输出: [[1, 2], [3, 4], [5, 6], [3, 4, 5]] (顺序保留)
对于字典的列表(list of dicts): 字典是不可哈希的。如果你想基于字典的内容去重,一个常见的做法是:
list_of_dicts = [
{'id': 1, 'name': 'Alice'},
{'id': 2, 'name': 'Bob'},
{'name': 'Alice', 'id': 1}, # 这是一个重复项,但键顺序不同
{'id': 3, 'name': 'Charlie'}
]
seen_hashes = set()
unique_dicts = []
for d in list_of_dicts:
# 将字典转换为可哈希的形式
# 确保键值对的顺序一致,以便生成相同的哈希
# 排序后的items()返回一个列表,再转为元组
dict_hashable = tuple(sorted(d.items()))
if dict_hashable not in seen_hashes:
seen_hashes.add(dict_hashable)
unique_dicts.append(d)
print(unique_dicts)
# 输出: [{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, {'id': 3, 'name': 'Charlie'}]这里我们通过
tuple(sorted(d.items()))
set
技巧三:自定义对象的 __hash__
__eq__
如果你处理的是自定义类的实例,并且希望它们能被用于
set
__hash__
__eq__
class MyObject:
def __init__(self, id, name):
self.id = id
self.name = name
# 定义相等性:当id和name都相同时,两个MyObject实例被认为是相等的
def __eq__(self, other):
if not isinstance(other, MyObject):
return NotImplemented
return self.id == other.id and self.name == other.name
# 定义哈希值:基于id和name的哈希值
# 注意:如果两个对象相等,它们的哈希值必须相等
def __hash__(self):
return hash((self.id, self.name))
def __repr__(self):
return f"MyObject(id={self.id}, name='{self.name}')"
objects = [
MyObject(1, 'A'),
MyObject(2, 'B'),
MyObject(1, 'A'), # 重复项
MyObject(3, 'C')
]
unique_objects = list(set(objects))
print(unique_objects) # 输出: [MyObject(id=1, name='A'), MyObject(id=2, name='B'), MyObject(id=3, name='C')]实现这两个魔法方法后,你的自定义对象就变得“哈希友好”了,可以和普通的可哈希对象一样,直接用
set
OrderedDict
在实际开发中,列表元素的顺序往往很重要。你可能不希望去重后,原本的排列被打乱。幸运的是,Python提供了几种既能去重又能保留原始顺序的方法。我个人在处理这类问题时,通常会在效率和代码简洁性之间做权衡。
使用 collections.OrderedDict.fromkeys()
OrderedDict
fromkeys()
from collections import OrderedDict my_list = ['apple', 'banana', 'orange', 'apple', 'grape', 'banana'] unique_ordered_list = list(OrderedDict.fromkeys(my_list)) print(unique_ordered_list) # 输出: ['apple', 'banana', 'orange', 'grape']
这个方法非常直观,一行代码就能搞定,而且底层实现基于哈希表,所以效率很高,平均时间复杂度是O(n)。这是我处理哈希able对象去重并保留顺序时的首选。
使用列表推导式与辅助 set
OrderedDict
set
my_list = ['apple', 'banana', 'orange', 'apple', 'grape', 'banana'] seen = set() unique_ordered_list = [item for item in my_list if item not in seen and not seen.add(item)] print(unique_ordered_list) # 输出: ['apple', 'banana', 'orange', 'grape']
这里的
not seen.add(item)
set.add()
None
not None
True
item
seen
item not in seen
True
seen.add(item)
not seen.add(item)
True
item
unique_ordered_list
item
seen
item not in seen
False
item
传统循环与辅助 set
my_list = ['apple', 'banana', 'orange', 'apple', 'grape', 'banana'] unique_ordered_list
以上就是python怎么从列表中删除重复项_python列表去重高效实现方法的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号