Python 怎么删除列表里的重复元素?附 4 种最实用方法

编程狮(w3cschool.cn) 2026-08-12 15:25:35 浏览数 (31)
反馈

Python 列表去重,就是把列表里重复出现的值只保留一份。你刚用 Python 抓完一批数据,或者读入一个 CSV 文件,打开列表一看:同一个用户名、同一件商品出现了好几遍。你只想让每个值只留一个,却不知道从哪下手。最干净的做法是用 set() 把列表转成集合,一行就能完成;如果你还需要保持原来的先后顺序,就用 dict.fromkeys()。今天这篇文章,编程狮就把四种做法一次讲清,从最简单的到适合大数据的都有,并告诉你每种该怎么选。

一、做 Python 列表去重前,先回答两个问题

在做 Python 列表去重之前,你要先想清楚两件事,因为它们直接决定用哪种方法,选错了要么顺序乱掉,要么代码又慢又绕。

第一个问题是顺序重不重要。有些场景你不在乎顺序,比如统计完去重后直接做集合运算;但更多时候你希望结果里元素的先后,和原列表第一次出现的顺序一致,比如保留用户最早点击的商品顺序。顺序要求不同,方法完全不同。

第二个问题是数据量有多大。几十条数据随便怎么写都行;但如果是几万、几十万行,就要考虑运行效率,这时候 pandas 往往比手写循环快得多。所以「怎么选」比「怎么写」更关键。

💡 小提示:如果你刚接触 Python,建议先过一遍 Python3 教程 把列表、循环、集合这些基础概念打牢,后面理解起来会快很多。

1.1 一个会踩坑的前提

很多初学者会下意识写出 new_list = list,以为这样能复制列表。其实这只是在给同一个列表起第二个名字,原列表一改,新「列表」也跟着改。复制要用 new_list = old_list.copy() 或者 list(old_list)。这个坑和去重无关,但几乎每个新手都会遇到,先提一句,免得你后面调试时一脸懵。

1.2 去重和「计数」是两件事

顺带提一句,去重解决的只是「每个值留一份」,如果你想知道「每个值出现了几次」,那是计数的活,方法完全不同。比如统计某个用户 ID 出现了多少遍,用字典计数比去重更合适。把这两个需求分清,才不会写出既没去干净又没数对的代码。

二、方法一:用 set 去重,最简单也最粗暴

set 是 Python 里的集合类型,它最大的特点就是「元素不重复」。所以把列表丢进 set,重复项会自动消失:

nums = [1, 2, 2, 3, 3, 3, 5]
result = list(set(nums))
print(result)  # 输出可能是 [1, 2, 3, 5](顺序不保证)

上面这段做的是把 nums 转成集合,集合会丢掉重复的数字,再用 list() 转回列表。三行里真正干活的是中间那一行。在 Python 列表去重里,set 去重是速度最快的一种,底层是哈希表,判断「这个值在不在里面」几乎是瞬间完成。

set 去重的优点就一个字:快,几万条数据也不在话下。它的代价也很明显:

words = ["banana", "apple", "banana", "cherry"]
print(list(set(words)))  # 顺序被重排,每次运行可能都不一样

上面这段输出顺序不固定,如果你的业务依赖「先来后到」,set 就不合适。另外,如果列表里混了不可哈希的类型(比如嵌套的列表、字典),直接转 set 会报错 TypeError: unhashable type

关于集合的更多常见操作,比如求交集、并集、差集,可以翻 Python 速查手册 随时查阅,里面把集合运算的写法列得很全。

三、方法二:用 dict.fromkeys 保序去重

如果你既想要去重,又想保留原顺序,Python 3.7 之后有个很巧妙的做法:利用字典的键不能重复、且会记住插入顺序的特性。

nums = [1, 2, 2, 3, 3, 3, 5]
result = list(dict.fromkeys(nums))
print(result)  # 输出 [1, 2, 3, 5],顺序和第一次出现一致

dict.fromkeys(nums) 会用 nums 里的每个元素作为键生成字典,重复的键只保留第一个,而字典会记住键的插入顺序。最后 list() 把键取出来,就得到了「去重且保序」的结果。

这个方法一行搞定,可读性也好,是日常 Python 列表去重里我最常推荐的保序写法。它的代价是和方法一一样,要求元素是「可哈希」的:数字、字符串、元组都可以,列表和字典不行。关于字典和序列的更多基础用法,这份 Python 教程 里也有系统讲解,适合你顺手补课。

四、方法三与方法四:seen 推导、以及 pandas 进阶

方法三适合你想完全掌控逻辑的时候。思路是用一个 seen 集合记住已经出现过的元素,配合列表推导式只保留第一次出现的:

nums = [1, 2, 2, 3, 3, 3, 5]
seen = set()
result = [x for x in nums if not (x in seen or seen.add(x))]
print(result)  # [1, 2, 3, 5]

这段的巧思在 seen.add(x) 会返回 None,所以 x in seen or seen.add(x)x 已存在时走前半段(过滤掉),不存在时走后半段(加进 seen 并因返回 None 被 not 成 True 保留)。第一次看会有点绕,但它保序、可控,还能顺手记录每个值出现了几次——这是 set 和 dict.fromkeys 都做不到的。

方法四面向大数据。当你在做 Python 列表去重,面对几万行表格数据时,手写循环太慢,直接用 pandas 的 drop_duplicates

import pandas as pd


df = pd.DataFrame({"user": ["a", "b", "a", "c", "b"], "score": [1, 2, 3, 4, 5]})
clean = df.drop_duplicates(subset=["user"], keep="first")
print(clean)

drop_duplicates 默认保留第一次出现的行,subset 指定按哪一列判断重复,keep 可以选 "first""last"False(全删)。面对十万行数据,它比任何手写循环都快得多。keep 还能取 "last" 保留最后一次出现的行,或 False 把重复行全删光,按场景挑就行。

如果你想把各种去重思路拆得更细,这篇 Python 列表去重详解 可以作为补充阅读,它覆盖了 set、推导式、循环、字典四种写法的逐项对比。

总结

Python 列表去重没有唯一答案,关键看你要不要顺序、数据有多大。要速度不在乎顺序,用 set 去重;要保序又要简洁,用 dict.fromkeys;要完全掌控逻辑并顺带计数,用 seen 加列表推导式;面对海量表格数据,直接上 pandas 的 drop_duplicates。

要点带走:

  • set 去重最快,但会打乱顺序,且元素必须可哈希;
  • dict.fromkeys 一行保序去重,日常最推荐;
  • seen 列表推导式能顺便统计出现次数;
  • 大数据清洗优先用 pandas,别手写循环。

下一步,把列表、集合、字典这三种结构的关系理清楚,你的 Python 数据清洗效率会再上一个台阶。

延伸学习

想把 Python 数据处理这块系统补齐,可以按这个顺序来:

  1. 先过一遍 Python 零基础到高薪就业,把基础语法和常用数据结构铺平;
  2. 遇到具体语法记不住时,翻 Python 开发方向 找系统学习路径。

常见问题

Q:为什么我用 set 去重后,列表顺序全乱了?
A:这是 set 的固有特性,集合本身不保存顺序。如果你需要保序,改用 dict.fromkeys 或 seen 列表推导式,这两种方法都会保留元素第一次出现的先后顺序。

Q:列表里嵌套了列表,转 set 报错怎么办?
A:嵌套列表是不可哈希类型,不能直接放进 set。可以先把它转成元组,或者用 seen 列表推导式配合自定义判断逻辑来处理,必要时也可以先扁平化再去重。

Q:pandas 的 drop_duplicates 怎么只按某一列去重?
A:给它传 subset 参数,比如 df.drop_duplicates(subset=["user"]) 就只按 user 这一列判断是否重复,其他列保持不变,默认保留第一次出现的那一行。

0 人点赞