Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
如何删除列表中的重复元素?_创想鸟

如何删除列表中的重复元素?

答案:Python中去重常用set、dict.fromkeys()和循环加辅助集合;set最快但无序,dict.fromkeys()可保序且高效,循环法灵活支持复杂对象去重。

如何删除列表中的重复元素?

删除列表中的重复元素,在Python中我们通常会利用集合(set)的特性,或者通过列表推导式、循环遍历等方式实现。每种方法都有其适用场景和性能考量,关键在于理解数据本身的特点以及对最终结果(如是否需要保留原始顺序)的要求。

解决方案

在Python中,处理列表去重有几种核心方法,它们各有优劣,适用于不同的场景。

1. 利用集合(Set)的特性这是最常见也通常是最简洁高效的方法,尤其适用于元素可哈希且不关心原始顺序的场景。

my_list = [1, 2, 2, 3, 4, 4, 5, 1, 6]unique_list = list(set(my_list))print(unique_list)# 输出: [1, 2, 3, 4, 5, 6] (顺序可能不同)

原理:

set

是无序不重复元素的集合。将列表转换为集合会自动去除重复项,再将其转换回列表即可。优点: 代码简洁,执行效率高。缺点: 无法保证原始元素的顺序。如果列表中包含不可哈希的元素(如列表、字典),则会抛出

TypeError

2. 使用

dict.fromkeys()

方法(Python 3.7+ 保持顺序)这个方法利用了字典键的唯一性,并且从Python 3.7开始,字典会保持插入顺序,因此它能很好地满足既去重又保持顺序的需求。

my_list = [1, 2, 2, 3, 4, 4, 5, 1, 6]unique_list = list(dict.fromkeys(my_list))print(unique_list)# 输出: [1, 2, 3, 4, 5, 6] (保留原始顺序)

原理:

dict.fromkeys(iterable)

会创建一个新字典,其键来自

iterable

中的元素,值默认为

None

。由于字典的键必须是唯一的,重复的元素会被自动忽略,而Python 3.7+的字典特性保证了键的插入顺序。优点: 简洁高效,保留原始顺序。缺点: 同样要求列表元素可哈希。

3. 循环遍历配合辅助集合(保留顺序且处理不可哈希元素前的准备)当你需要保留原始顺序,并且可能需要更精细的控制,或者列表元素可能不可哈希时,这种方法提供了一种更通用的思路。

my_list = [1, 2, 2, 3, 4, 4, 5, 1, 6]unique_list = []seen = set() # 用一个set来跟踪已经见过的元素for item in my_list:    if item not in seen:        unique_list.append(item)        seen.add(item)print(unique_list)# 输出: [1, 2, 3, 4, 5, 6] (保留原始顺序)

原理: 遍历原列表,用一个

set

seen

)来记录已经添加到新列表中的元素。每次检查当前元素是否已在

seen

中,不在则添加到新列表和

seen

中。优点: 保留原始顺序,灵活性高,可以扩展处理更复杂的去重逻辑。缺点: 相较于直接使用

set

dict.fromkeys()

,代码量稍多,对于非常大的列表,性能可能略逊。

掌握不同去重策略:效率与场景的权衡

选择哪种去重策略,往往不是“最好”与“最差”的问题,而是“最适合”与“不适合”的考量。在我看来,这背后是对效率、代码可读性以及特定场景需求的综合权衡。

首先,Set转换法无疑是最直观、最“Pythonic”的去重方式,尤其当你的列表元素都是像数字、字符串、元组这类可哈希类型,并且你对元素的最终顺序没有严格要求时。它的底层实现通常是哈希表,查找和插入的平均时间复杂度接近O(1),因此在大数据量下去重效率极高。但它的局限性也很明显,一旦遇到列表、字典这类不可哈希的对象,它就会直接报错,这在处理复杂数据结构时是个障碍。

其次,

dict.fromkeys()

方法(特别是Python 3.7+版本)提供了一个优雅的解决方案,它在保持

set

高效去重能力的同时,解决了顺序丢失的问题。如果你正在使用较新的Python版本,并且数据类型可哈希,那么这个方法往往是我个人首选,因为它既简洁又高效,同时满足了顺序需求。它的效率也得益于字典内部的哈希表实现。

最后,循环遍历配合辅助集合的方法,虽然代码量相对多一些,但它的通用性和灵活性是前两者无法比拟的。当你的列表元素不可哈希,或者你需要根据元素的某个特定属性(而不是整个元素)来判断重复时,这种方法就能派上用场。例如,你有一堆自定义对象,你可能需要根据它们的

id

属性来判断是否重复,而不是对象本身的内存地址。这种方法允许你自定义“相等”的逻辑,通过在

seen

集合中存储一个可哈希的“键”来实现。它的性能取决于循环次数和

in

操作的效率,对于哈希表来说,

in

操作通常也是O(1)的平均时间复杂度。

总的来说,如果数据简单且顺序不重要,用

set

;如果数据简单且顺序重要,用

dict.fromkeys()

;如果数据复杂或需要自定义去重逻辑,那么循环遍历配合辅助集合是更稳妥的选择。

处理复杂数据类型去重:不仅仅是数字和字符串

当列表中的元素不再是简单的数字或字符串,而是嵌套列表、字典、自定义对象时,去重就变得有些棘手了。因为

set

dict.fromkeys()

都要求元素是“可哈希”的。

1. 处理嵌套列表或字典(不可哈希对象)

直接将包含列表或字典的列表转换为

set

会报错:

TypeError: unhashable type: 'list'

unhashable type: 'dict'

解决方案:

将不可哈希元素转换为可哈希形式:如果嵌套列表的内部元素是可哈希的,可以将其转换为元组(tuple),因为元组是不可变的,因此是可哈希的。字典则可以转换为

frozenset

(如果只关心键值对的存在,不关心顺序),或者将其序列化成字符串。

list_of_lists = [[1, 2], [3, 4], [1, 2], [5, 6], [3, 4]]# 将内部列表转换为元组,然后使用set去重unique_lists_tuples = set(tuple(item) for item in list_of_lists)unique_lists = [list(item) for item in unique_lists_tuples]print(unique_lists)# 输出: [[1, 2], [3, 4], [5, 6]] (顺序不确定)list_of_dicts = [{'a': 1, 'b': 2}, {'b': 2, 'a': 1}, {'c': 3}]# 字典转换为frozenset,前提是字典的键和值都是可哈希的# 注意:frozenset不保证顺序,且键值对需要转换为元组unique_dicts_frozenset = set(frozenset(d.items()) for d in list_of_dicts)unique_dicts = [dict(item) for item in unique_dicts_frozenset]print(unique_dicts)# 输出: [{'a': 1, 'b': 2}, {'c': 3}] (顺序不确定,且frozenset可能打乱原始字典键值对的顺序)

这种方法虽然有效,但需要注意转换过程可能带来的数据结构变化和顺序问题。

自定义比较逻辑配合辅助集合:这是最灵活的方式,尤其适用于当“重复”的定义比较复杂时。你可以定义一个函数来为每个复杂对象生成一个“哈希键”,然后用这个键来判断重复。

# 假设我们有一堆用户字典,我们认为只要'id'相同就是重复用户users = [    {'id': 1, 'name': 'Alice', 'age': 30},    {'id': 2, 'name': 'Bob', 'age': 25},    {'id': 1, 'name': 'Alicia', 'age': 31}, # id为1的重复    {'id': 3, 'name': 'Charlie', 'age': 35},    {'id': 2, 'name': 'Robert', 'age': 26}  # id为2的重复]unique_users = []seen_ids = set() # 用来存储已经见过的用户IDfor user in users:    user_id = user['id'] # 提取作为判断重复的“键”    if user_id not in seen_ids:        unique_users.append(user)        seen_ids.add(user_id)print(unique_users)# 输出: [{'id': 1, 'name': 'Alice', 'age': 30}, {'id': 2, 'name': 'Bob', 'age': 25}, {'id': 3, 'name': 'Charlie', 'age': 35}]

这种方法保留了原始对象的完整性,并且可以根据业务逻辑精确定义“重复”的含义。

2. 处理自定义对象

如果你的列表包含自定义类的实例,并且你希望根据它们的某个或某些属性来去重,你有两种主要做法:

重写

__eq__

__hash__

方法:这是最“面向对象”的方式。通过在类中定义这两个特殊方法,你可以让Python知道如何比较你的对象是否相等,以及如何为它们生成哈希值。一旦定义了,你的自定义对象就可以直接放入

set

中去重了。

class Product:    def __init__(self, sku, name, price):        self.sku = sku        self.name = name        self.price = price    def __eq__(self, other):        if not isinstance(other, Product):            return NotImplemented        return self.sku == other.sku # 假设sku是唯一标识    def __hash__(self):        return hash(self.sku) # 必须与__eq__逻辑一致    def __repr__(self):        return f"Product(sku='{self.sku}', name='{self.name}', price={self.price})"products = [    Product('A001', 'Laptop', 1200),    Product('A002', 'Mouse', 25),    Product('A001', 'Gaming Laptop', 1500), # sku重复    Product('A003', 'Keyboard', 75),    Product('A002', 'Wireless Mouse', 30)   # sku重复]unique_products = list(set(products))print(unique_products)# 输出: [Product(sku='A001', name='Laptop', price=1200), Product(sku='A002', name='Mouse', price=25), Product(sku='A003', name='Keyboard', price=75)]

注意: 重写

__eq__

时,通常也要重写

__hash__

,并且要确保

a == b

为真时,

hash(a) == hash(b)

也为真。

使用辅助集合提取关键属性去重(不修改类)如果不想修改类的定义,或者去重逻辑只是临时性的,可以使用上面处理字典的类似方法:提取对象的某个(或多个)属性作为哈希键。

# 沿用上面的Product类,但假设我们不能修改它products_no_hash = [    Product('A001', 'Laptop', 1200),    Product('A002', 'Mouse', 25),    Product('A001', 'Gaming Laptop', 1500),    Product('A003', 'Keyboard', 75),    Product('A002', 'Wireless Mouse', 30)]unique_products_by_sku = []seen_skus = set()for product in products_no_hash:    if product.sku not in seen_skus:        unique_products_by_sku.append(product)        seen_skus.add(product.sku)print(unique_products_by_sku)# 输出: [Product(sku='A001', name='Laptop', price=1200), Product(sku='A002', name='Mouse', price=25), Product(sku='A003', name='Keyboard', price=75)]

这种方法灵活,不需要修改原始类,但需要手动编写循环逻辑。

场景化决策:何时选择最适合的去重方案?

在实际开发中,面对去重需求,我通常会从以下几个维度来思考和选择最合适的方案:

1. 数据规模和性能要求:

小规模列表(几百到几千元素): 绝大多数方法都能胜任,性能差异不明显。选择代码最简洁、最易读的即可,比如

list(set(my_list))

list(dict.fromkeys(my_list))

大规模列表(数万到数百万元素): 性能成为关键。

set

转换法和

dict.fromkeys()

通常是最快的选择,因为它们底层依赖哈希表,平均时间复杂度接近O(N)。而使用

item not in new_list

的循环遍历方法(没有辅助

set

)会因为

in

操作在列表中是O(N)而导致总复杂度达到O(N^2),这在大数据量下是不可接受的。

2. 是否需要保留原始顺序:

不关心顺序:

list(set(my_list))

是最直接的选择。必须保留顺序: Python 3.7+版本,

list(dict.fromkeys(my_list))

是首选。如果版本较低,或者需要更强的兼容性,那么循环遍历配合辅助

set

是可靠的方案。

3. 列表元素的类型:

简单可哈希类型(数字、字符串、元组): 所有方法都适用。根据顺序需求和代码简洁性来选择。复杂不可哈希类型(列表、字典、自定义对象):如果能转换为可哈希的表示(如列表转元组),可以先转换再用

set

。如果需要根据对象的某个属性去重,或者去重逻辑比较复杂,那么自定义循环遍历配合辅助

set

(存储对象的哈

以上就是如何删除列表中的重复元素?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1370041.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
谈谈你对Python描述符(Descriptor)的理解。
上一篇 2025年12月14日 10:11:11
如何理解Python的“一切皆对象”?
下一篇 2025年12月14日 10:11:28

相关推荐

  • 在Java中如何实现对象的唯一标识

    答案:Java中实现对象唯一标识主要有四种方式:1. 使用UUID生成全局唯一ID,适用于无数据库或分布式场景;2. 利用数据库自增主键,通过JPA的@Id和@GeneratedValue实现持久化唯一性;3. 重写equals与hashCode方法,基于不可变业务字段保证逻辑唯一;4. 采用Sno…

    2026年9月21日
    000
  • 为什么iPhone14Plus系统更新后屏幕失灵如何强制重启?快速按音量键后按电源

    为什么iPhone14Plus系统更新后屏幕失灵如何强制重启?快速按音量键后按电源为什么iPhone14Plus系统更新后屏幕失灵如何强制重启?快速按音量键后按电源为什么iPhone14Plus系统更新后屏幕失灵如何强制重启?快速按音量键后按电源为什么iPhone14Plus系统更新后屏幕失灵如何强制重启?快速按音量键后按电源

    如果您尝试访问某个网站,但服务器无法访问,则可能是由于服务器 IP 地址无法解析。以下是解决此问题的步骤: 本文运行环境:iPhone 14 Plus,iOS 18。 一、强制重启设备 当iPhone 14 Plus在系统更新后出现屏幕失灵、无响应或触控失效时,强制重启是一种有效的硬件级恢复手段,可…

    2026年9月21日 用户投稿
    100
  • PHP中基于参考数组过滤多维数组并保持结构一致性

    本教程详细阐述了如何在PHP中,根据一个参考数组来过滤多维数组的特定子数组,并同步移除其他子数组中对应索引的元素,最终实现数组的结构化筛选和重新索引。文章通过实际案例和代码演示,指导读者高效地处理复杂数组的匹配与清理任务。 在php开发中,我们经常会遇到需要对复杂数据结构进行筛选和整理的场景。例如,…

    2026年9月21日
    000
  • VSCode语言特性贡献点配置

    通过配置package.json中的contributes字段可实现VSCode语言扩展,依次需设置语法高亮(grammars)、语言绑定(languages)、激活事件(activationEvents)及语言服务器功能(如补全、跳转),并定义language-configuration.json…

    2026年9月21日
    000
  • 美图秀秀图片亮度无法调节怎么办 美图秀秀亮度调整与修复方法

    亮度调不了可能是未进入“美化”或“编辑”模式,需确认已正确导入图片并找到亮度滑块;2. 软件版本过旧或缓存异常会导致功能失效,应更新美图秀秀或重启程序,电脑版可尝试以管理员身份运行;3. 不同设备可能存在兼容性问题,建议切换手机App或电脑客户端测试,手机用户可清除缓存或重装应用;4. 若功能仍不可…

    2026年9月21日
    000
  • 长佩阅读如何自定义封面

    在长佩阅读中,设置自定义封面可以让你的书架更具个人风格。以下是具体操作步骤: 一、确认书籍是否支持自定义封面 并非所有书籍都开放自定义封面功能,你需要先进入书籍详情页查看是否存在“自定义封面”这一选项。若该按钮存在,则说明这本书允许用户更换封面。 二、准备合适的封面图片 选择一张你喜欢的图片作为新封…

    2026年9月21日
    000
  • Laravel 8 登录后重定向到仪表盘的完整教程

    本教程详细介绍了在 Laravel 8 中实现用户登录后重定向到仪表盘的多种方法。我们将探讨如何利用 Laravel 内置的 $redirectTo 属性,以及如何通过重写 LoginController 中的 login 方法来实现自定义重定向逻辑。此外,教程还将重点讲解正确的路由配置和中间件使用…

    2026年9月21日
    000
  • 探探App如何更新应用版本_探探App应用版本更新教程及自动升级设置

    打开App Store点击更新标签,找到探探并手动点击更新;2. 开启自动更新需进入设置-App Store,打开自动下载的App更新开关;3. 搜索探探查看是否显示“更新”以确认版本状态。 探探App更新很简单,无论是手动升级还是设置自动更新,都能快速用上最新版本。下面告诉你具体怎么操作。 手动更…

    2026年9月21日
    000
  • 使用本地HTML文件运行JavaScript脚本失败的原因及解决方案

    本文旨在帮助开发者理解在没有Web服务器的情况下,直接通过浏览器打开本地HTML文件时,JavaScript脚本可能无法正常运行的原因,并提供相应的解决方案。文章将深入探讨浏览器安全策略、相对路径问题以及如何正确引入和执行JavaScript脚本,确保你的HTML、CSS和JavaScript代码能…

    2026年9月21日
    000
  • 番茄免费小说怎么用QQ登录_番茄免费小说QQ登录教程

    首先通过登录界面点击“QQ登录”授权进入,或在账号设置中绑定QQ;若已绑定手机号,则需输入验证码完成验证,最后确认授权即可成功登录。 如果您希望在番茄免费小说中使用QQ账号进行登录,但找不到正确的操作入口或遇到授权问题,可以按照以下方法尝试。这些步骤能帮助您完成账号关联和登录流程。 本文运行环境:小…

    2026年9月21日
    200
  • VSCode怎么看效果_VSCode实时预览和调试代码运行效果教程

    VSCode通过实时预览扩展和内置调试器实现代码效果查看。使用Live Server可实时预览前端页面,保存即刷新;Markdown文件支持侧边预览。调试功能需配置launch.json,支持Node.js、Python、浏览器端JavaScript等,通过断点、变量监视、调用堆栈等深入分析代码执行…

    2026年9月21日
    000
  • 使用正则表达式检测字符串中的除零操作

    本文详细介绍了如何使用正则表达式精确检测字符串中潜在的除零操作。针对表达式中可能存在的变量引用(如<>)、数字、多余空格以及禁止包含引号等复杂情况,文章提供了一个高效的正则表达式模式,并深入解析其构成原理。通过具体的Java代码示例,读者将学习如何将此模式应用于实际编程场景,从而有效识别…

    2026年9月21日
    000
  • iPhone14首次使用时应禁用的几项功能

    哪些功能在新机设置时建议关闭? 1. “定位服务” 启用定位服务后,各类应用可获取您的实时位置,虽然有助于导航或本地推荐,但也可能造成位置信息被滥用。若重视个人隐私,建议进入设置关闭该权限,限制应用对地理位置的访问。 2. “后台应用刷新” 此功能使应用程序在未打开时也能在后台获取最新内容,提升使用…

    2026年9月21日
    000
  • 如何从被调用类中获取调用者文件的命名空间

    本文探讨了在PHP中,如何在不通过参数传递的情况下,从一个被调用的工具类中获取到调用该方法的文件的命名空间。通过结合使用`debug_backtrace()`回溯调用栈以定位调用者文件,并利用`token_get_all()`解析文件内容来提取命名空间声明,提供了一种实用的解决方案。文章详细介绍了实…

    2026年9月21日
    000
  • 构建Spring自定义Kafka配置的注解式解决方案

    本文探讨了在Spring Boot应用中通过自定义注解实现Kafka配置自动化时遇到的挑战,特别是由于Bean注册时机不当导致的依赖注入失败。我们将深入分析问题根源,并提供两种核心解决方案:利用META-INF/spring.factories实现标准化的自动配置发现,以及通过ImportBeanD…

    2026年9月21日
    1100
  • 悟空浏览器开发者工具的控制台怎么用_悟空浏览器Console控制台使用入门教程

    首先启用悟空浏览器开发者工具并进入Console标签,可查看错误、警告等日志信息,通过过滤功能定位问题;支持执行JavaScript代码实时调试,监控网络请求失败及全局异常,还可清空或保存日志以便分析。 如果您在使用悟空浏览器进行网页开发或调试时,发现页面元素未按预期工作或脚本报错,则可以借助开发者…

    2026年9月21日
    700
  • 美团外卖节日优惠券领取入口_美团节日活动优惠券获取方法

    节日期间可通过美团外卖首页“膨胀红包”、搜索品牌关键词、参与“神抢手”秒杀、邀请好友助力及关注官方社交媒体口令等五种方法领取优惠券,具体包括完成任务积累红包、领取0元饮品券、抢购低价商品券、获取大额免单券和兑换口令红包。 如果您在节日期间准备通过美团外卖订餐,但未能找到可用的优惠券入口,则可能是由于…

    2026年9月21日
    100
  • MAC系统磁盘空间不足怎么办_Mac磁盘空间清理与管理技巧

    Mac存储空间不足时,应先使用系统自带的存储管理工具分析并优化存储,通过“关于本机”进入“管理”界面,启用优化选项;接着手动删除不常用应用及其在Application Support和Caches中的残留文件;再进入资源库清理Caches和Logs中的缓存与日志;随后在“避免杂乱”中查找并删除大型无…

    2026年9月21日
    000
  • 实现搜索结果的 A-Z 排序:PHP 教程

    本文档旨在指导开发者如何在 PHP 中实现搜索结果的 A-Z 排序功能。通过结合 AJAX 技术和 PHP 函数,可以方便地对通过 POST 方法获取的医生搜索结果进行 A-Z 排序,从而优化用户浏览体验。本文将详细介绍实现步骤,提供可复用的代码示例,并着重强调注意事项,旨在帮助开发者快速掌握并应用…

    2026年9月21日
    000
  • MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南MySQL全文搜索引擎集成方案_提升文本数据搜索能力的实用指南

    mysql原生全文搜索功能存在明显局限,需结合外部搜索引擎才能满足复杂需求。1. mysql全文搜索适用于小数据量、简单查询场景,但分词能力弱,尤其对中文支持差,查询功能有限,无法实现模糊查询、纠错等高级功能,且性能随数据量增长显著下降。2. 外部搜索引擎如elasticsearch(es)和sph…

    2026年9月21日 用户投稿
    000

发表回复

登录后才能评论
关注微信