最直接去重方法是使用set(),但会丢失顺序;若需保留顺序且元素可哈希,推荐dict.fromkeys();对于不可哈希元素或复杂结构,应采用手动迭代结合辅助集合的方式。

Python中要将列表中的所有元素去重,最直接也最常用的方法是利用
set
dict.fromkeys()
在Python中处理列表去重,我通常会根据几个关键因素来选择方法:原始顺序是否重要?列表中的元素是否都是可哈希的?以及对性能的要求有多高?
1. 最简洁高效:利用 set()
这是我最常推荐的方法,因为它极其简洁且效率高,尤其适用于元素顺序无关紧要的场景。
set
立即学习“Python免费学习笔记(深入)”;
my_list = [1, 2, 2, 3, 4, 4, 5, 'a', 'b', 'a'] unique_list_unordered = list(set(my_list)) print(unique_list_unordered) # 可能会输出类似:[1, 2, 3, 4, 5, 'a', 'b'],顺序不确定
这种方法的核心在于
set()
list()
2. 兼顾效率与顺序:利用 dict.fromkeys()
如果你既想去重又想保留原始元素的插入顺序,那么从Python 3.7开始,
dict.fromkeys()
my_list = [1, 2, 2, 3, 4, 4, 5, 'a', 'b', 'a'] unique_list_ordered = list(dict.fromkeys(my_list)) print(unique_list_ordered) # 输出:[1, 2, 3, 4, 5, 'a', 'b']
dict.fromkeys(iterable)
iterable
None
对于Python 3.6及更早版本,如果你需要保留顺序,可以使用
collections.OrderedDict
from collections import OrderedDict my_list = [1, 2, 2, 3, 4, 4, 5, 'a', 'b', 'a'] unique_list_ordered_old_python = list(OrderedDict.fromkeys(my_list)) print(unique_list_ordered_old_python) # 输出:[1, 2, 3, 4, 5, 'a', 'b']
3. 手动迭代与辅助集合:最灵活但稍显繁琐
当列表中的元素包含不可哈希类型(如列表、字典本身)时,或者你需要更精细的控制逻辑时,基于循环和辅助集合的方法就派上用场了。
my_list = [1, 2, [3, 4], 2, [3, 4], 5, {'a': 1}, {'a': 1}] # 包含不可哈希元素
unique_list = []
seen = set() # 用于存储已见过的、可哈希的元素
for item in my_list:
# 对于可哈希元素,直接用set判断
if isinstance(item, (int, str, float, tuple)): # 假设这些是可哈希的
if item not in seen:
unique_list.append(item)
seen.add(item)
else: # 对于不可哈希元素(如列表、字典),需要特殊处理
# 这里的逻辑会比较复杂,取决于你如何定义“重复”
# 比如,对于字典,你可以比较特定键的值
# 对于列表,你可以将其转换为元组再比较
# 示例:假设我们想去重字典,根据其'a'键的值
if isinstance(item, dict) and 'a' in item:
item_id = item['a']
if item_id not in seen:
unique_list.append(item)
seen.add(item_id) # 记录的是键的值,而不是字典本身
elif isinstance(item, list):
# 将列表转换为元组进行哈希和比较
item_tuple = tuple(item)
if item_tuple not in seen:
unique_list.append(item)
seen.add(item_tuple)
else: # 其他不可哈希类型,直接添加(或者根据业务逻辑处理)
# 这部分需要根据实际需求来定,这里只是一个示例
if item not in unique_list: # 这种判断效率较低,O(N)
unique_list.append(item)
print(unique_list)
# 示例输出(取决于具体逻辑):[1, 2, [3, 4], 5, {'a': 1}]这个方法虽然看起来复杂,但它的优势在于灵活性。你可以完全控制如何定义“重复”,尤其是在处理嵌套列表、字典或自定义对象时,这往往是唯一的出路。
seen
in
set()
使用
set()
首先,也是最明显的一点,set()
set
set()
其次,也是一个更深层次的限制,
set()
list
dict
set(my_list)
TypeError: unhashable type: 'list'
'dict'
举个例子:
my_list_with_lists = [1, 2, [3, 4], 2, [3, 4]] # unique_list = list(set(my_list_with_lists)) # 这行代码会报错! # TypeError: unhashable type: 'list'
在这种情况下,
set()
当列表中的元素不再是简单的数字或字符串,而是嵌套的列表、字典,或者是自定义对象时,去重就变得有挑战性了。
set()
1. 将不可哈希元素转换为可哈希形式
对于包含列表的列表,如果内部列表的顺序和内容决定了其“唯一性”,我们可以将其转换为元组。元组是不可变的,因此是可哈希的。
list_of_lists = [[1, 2], [3, 4], [1, 2], [5, 6], [4, 3]] # 将每个内部列表转换为元组,然后用set去重 unique_tuples = set(tuple(item) for item in list_of_lists) unique_list_of_lists = [list(item) for item in unique_tuples] print(unique_list_of_lists) # 输出:[[1, 2], [3, 4], [5, 6], [4, 3]] (顺序不保证)
如果你需要保留原始顺序,可以结合
dict.fromkeys()
unique_list_of_lists_ordered = [list(item) for item in dict.fromkeys(tuple(item) for item in list_of_lists)] print(unique_list_of_lists_ordered) # 输出:[[1, 2], [3, 4], [5, 6], [4, 3]]
对于包含字典的列表,情况会更复杂一些,因为字典的键值对顺序通常不重要,但其内容定义了唯一性。如果字典内部的键值对也是可哈希的,可以将其转换为
frozenset
list_of_dicts = [
{'id': 1, 'name': 'Alice', 'age': 30},
{'id': 2, 'name': 'Bob', 'age': 25},
{'id': 1, 'name': 'Alice', 'age': 31}, # id为1,但age不同
{'id': 3, 'name': 'Charlie', 'age': 35},
{'id': 2, 'name': 'Bob', 'age': 25} # id为2,name和age都相同
]
# 策略1:根据某个唯一标识键(如'id')去重
unique_by_id = []
seen_ids = set()
for d in list_of_dicts:
if d['id'] not in seen_ids:
unique_by_id.append(d)
seen_ids.add(d['id'])
print("按ID去重:", unique_by_id)
# 输出:[{'id': 1, 'name': 'Alice', 'age': 30}, {'id': 2, 'name': 'Bob', 'age': 25}, {'id': 3, 'name': 'Charlie', 'age': 35}]
# 策略2:如果整个字典的内容(键值对)都相同才算重复
# 可以将字典的items()转换为frozenset(如果值都是可哈希的)
unique_by_content = []
seen_contents = set()
for d in list_of_dicts:
# frozenset(d.items()) 要求字典的值也是可哈希的
# 如果值是列表或字典,这里会报错,需要进一步处理
dict_content_hashable = frozenset(d.items())
if dict_content_hashable not in seen_contents:
unique_by_content.append(d)
seen_contents.add(dict_content_hashable)
print("按内容去重:", unique_by_content)
# 输出:[{'id': 1, 'name': 'Alice', 'age': 30}, {'id': 2, 'name': 'Bob', 'age': 25}, {'id': 1, 'name': 'Alice', 'age': 31}, {'id': 3, 'name': 'Charlie', 'age': 35}]
# 注意:这里id=1的两个字典被认为是不同的,因为age不同这种方法要求我们明确如何定义“重复”,并根据这个定义来构造一个可哈希的“指纹”。
2. 自定义比较函数(迭代法)
当上述方法都无法满足需求,或者元素类型非常复杂,难以转换为统一的可哈希形式时,我们可能需要退回到最原始的迭代方法,并编写自定义的比较逻辑。这种方法通常涉及一个嵌套循环,但我们可以通过一个辅助集合来优化性能。
class MyCustomObject:
def __init__(self, id, value):
self.id = id
self.value = value
# 如果要让set/dict.fromkeys直接去重,需要实现__hash__和__eq__
# 但这里我们假设没有实现,或者需要更复杂的去重逻辑
def __repr__(self):
return f"MyCustomObject(id={self.id}, value='{self.value}')"
list_of_objects = [
MyCustomObject(1, 'A'),
MyCustomObject(2, 'B'),
MyCustomObject(1, 'C'), # ID相同,但value不同
MyCustomObject(3, 'D'),
MyCustomObject(2, 'B') # ID和value都相同
]
unique_objects = []
seen_identifiers = set() # 存储用于判断唯一性的标识符
for obj in list_of_objects:
# 假设我们认为只要id相同就认为是重复的
identifier = obj.id
if identifier not in seen_identifiers:
unique_objects.append(obj)
seen_identifiers.add(identifier)
print("按ID去重自定义对象:", unique_objects)
# 输出:[MyCustomObject(id=1, value='A'), MyCustomObject(id=2, value='B'), MyCustomObject(id=3, value='D')]这种方法赋予了我们最大的控制权,能够处理几乎所有复杂的去重场景。关键在于如何设计
identifier
item not in seen_identifiers
identifier
set
seen_identifiers
在Python编程中,选择合适的去重方法不仅仅是实现功能,更要考虑其在不同场景下的性能表现。一个“明智”的选择,往往是在功能正确的前提下,兼顾时间复杂度和空间复杂度。
1. set()
list(set(my_list))
set()
2. dict.fromkeys()
list(dict.fromkeys(my_list))
set()
set()
以上就是Python怎么把列表中的所有元素去重_Python列表去重技巧与方法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号