python去重列表中相同的字典元素

news2025/1/23 3:21:22

python去重列表中相同的字典元素

文章目录

    • python去重列表中相同的字典元素
        • 一.知识点
        • 二.代码
          • |代码1
            • |问题
          • |代码2
        • 三.分析总结
          • 1、分析
          • 2、总结
        • 四.后续
          • 代码
          • 知识点
          • 代码流程
          • 问题
          • 总结
          • 总结

一.知识点

​ data_list = [{“a”: 1, “b”: 2}, {“a”: 2, “b”: 3}, {“a”: 1, “b”: 2}, {“a”: 3, “b”: 4}, {“a”: 2, “b”: 3}, {“a”: 1, “b”: 2}]

​ 萌新会犯的错误:使用集合来去重

​ print(set(data_list))

​ 会报错,因为字典是不可哈希的类型,不能直接用于集合的创建。如果要将字典元素去重,可以先将字典转化为元组再使用集合去重。

​ 在Python中,集合是可变的数据类型,因此不是可哈希的。集合的元素必须是可哈希的类型。如果集合中有不可哈希的元素,例如列表或字典,会引发TypeError错误。

​ 在 Python 中,可哈希的类型包括:

​ 不可变类型:例如数字、字符串、元组等,它们一旦创建,其值就不能被修改;
​ 可变类型但是不包含可变类型的元素:例如 frozenset 等;
​ 用户自定义的对象,只要实现了 hasheq 方法,使得对象在比较时可哈希即可。

需要注意的是,可哈希的类型必须实现了 hash 方法,使得相同的值具有相同的哈希值,这是哈希表能够正确工作的前提。

二.代码

|代码1

那就创建一个新列表,循环遍历嵌套着字典数据的列表,判断字典元素是否存在,若不在,就添加进去

def list_dict_duplicate_removal1(data_list):
    unique_list = []
    for data in data_list:
        if data not in unique_list:
            unique_list.append(data)
    return unique_list
|问题

当我在编写项目时,数据集比较大,有19万多行,如下图,元素即字典的键值对数量有14对

在这里插入图片描述

|代码2
	当数据集较大时,每次都需要遍历整个结果列表,查看当前字典是否已经存在于结果列表中,因此时间复杂度很高,导致程序运行变慢。一个更好的解决方案是使用哈希表来快速判断字典是否已经存在于结果列表中,使用哈希表实现去重的示例代码:
def list_dict_duplicate_removal2(data_list):
    result = []
    seen = set()
    for d in data_list:
        t = tuple(sorted(d.items()))
        if t not in seen:
            seen.add(t)
            result.append(d)
    return result

处理数据所用的时间明显很短,如下图

在这里插入图片描述

​ 在这个实现中,我们使用一个集合 seen 来记录已经出现过的字典。每个字典都被转换为一个元组,元组中的元素是字典项的键值对,使用 sorted() 函数可以确保元组中的键值对按照字典序排序,这样即使字典中的键值对顺序不同,元组也能够保持一致。然后将这个元组作为哈希表的键,将字典本身作为值,存入结果列表中。

三.分析总结

1、分析

​ 待去重的字典中的键值对数量较小,那么两段代码的差异可能不太明显。则使用第一段代码的处理速度可能会更快,因为它仅仅是简单地遍历了列表并将不重复的元素添加到另一个列表中。

​ 而第二段代码中,每个字典都被转换成一个元组并排序,这会比第一段代码中的简单遍历更加复杂和耗时。此外,第二段代码中还需要维护一个额外的集合来跟踪已经出现过的元素,这也会增加代码的复杂性和开销。不过,如果待去重的字典中的键值对数量较小,那么两段代码的差异可能不太明显。

​ 在实际使用中,应该根据具体情况选择合适的方法,对于复杂度比较高的数据结构,考虑使用第二段代码进行去重。

2、总结

其它知识点:

(1)哈希表相关知识
哈希表是一种非常常用和高效的数据结构,它可以帮助我们快速地在大量数据中查找、插入或删除元素。为了更好地理解哈希表的实现原理,可以将它比喻成一个大的盒子,盒子里面有很多抽屉,每个抽屉可以放置一个元素。在哈希表中,我们通常使用关键字来访问和操作元素,就像是在盒子中寻找某一个物品一样。为了确定一个元素的位置,我们需要将其关键字通过一个函数进行映射,从而得到该元素所在的抽屉。这个函数就是哈希函数。

​ 哈希表是一种数据结构,可以通过哈希函数将元素映射到数组的一个位置。哈希函数将任意长度的输入(例如字典对象)映射到固定长度的输出(例如整数),输出通常称为哈希值。哈希表通过将元素的哈希值作为下标来访问数组中的元素。因此,在哈希表中查找元素的时间复杂度是O(1),也就是说,它具有非常高的查找效率。

​ 哈希函数将关键字映射到一个整数值,然后通过将该整数值与数组的长度取余数,得到该元素在数组中的位置。如果不同的关键字映射到了同一个位置,就称为哈希冲突。为了解决哈希冲突,通常的做法是使用链表等数据结构来存储同一个位置上的多个元素。这就相当于在同一个抽屉里面放置了多个物品,通过链表的方式可以将它们区分开来。

​ 使用哈希表可以实现O(1)的查找、插入和删除操作,也就是说,不论哈希表中有多少个元素,操作所需要的时间都是固定的,这样就大大提高了程序的效率。但是需要注意的是,哈希函数的设计需要具有良好的性质,这样才能避免哈希冲突的发生,从而保证哈希表的效率和准确性。

​ 当我们需要在一个很大的数据集合中查找某个元素时,传统的做法是遍历整个集合,一个一个地比较元素,这种做法的时间复杂度是O(n),其中n是集合中元素的数量。当集合很大时,这种做法就会非常耗时。

(2)第二段代码在哈希表的应用

​ 哈希表是 seen,它是一个 Python 内置的 set 类型,用于存储不重复的元素。

​ 哈希函数是 tuple(sorted(d.items())),它将字典对象 d 转换为一个元组,并按照元素顺序排序,以确保对于相同的键值对,生成的元组是相同的。

​ 哈希值是 t,它是由哈希函数生成的元组。哈希函数将任意长度的字典对象映射到固定长度的元组。

​ 这里的哈希函数使用了 Python 内置的 tuple 函数和 sorted 函数。函数中的第 4 行可以体现哈希函数将任意长度的输入映射到固定长度的输出。

四.后续

代码

分析下面的代码(当时着急,粘贴了一份网上代码来处理数据),回顾一下redece()函数和lambda表达式

from functools import reduce
def list_dict_duplicate_removal3(data_list):
    run_function = lambda x, y: x if y in x else x + [y]
    return reduce(run_function, [[],] + data_list)
知识点

(1)reduce()函数
reduce()函数会对参数序列中元素进行累积。函数将一个数据集合(链表,元组等)中的所有数据进行下列操作:用传给 reduce 中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用 function 函数运算,最后得到一个结果。

(2)lambda表达式:匿名函数
匿名函数lambda x: x * x实际上就是:
def f(x):return x * x
关键字lambda表示匿名函数,冒号前面的x表示函数参数。

代码流程

该函数引用了 reduce() 函数和 lambda 表达式:

from functools import reduce

​ reduce() 函数是 Python 2.x 中的内置函数,在 Python 3.x 中被移至 functools 模块。它可以对序列类型(如列表、元组)中的元素进行迭代处理,并返回一个最终结果。该函数接收两个参数,第一个参数是函数对象,第二个参数是迭代器(可迭代对象)。
​ lambda 表达式是一种匿名函数,即没有名称的函数。它可以接收任意多个参数,但只能有一个表达式,且返回值就是该表达式的结果。lambda 表达式通常用于定义简单的函数,并将其作为参数传递给其他函数。

​ 函数中定义了一个 run_function 的 lambda 函数,用来对比和过滤列表中的元素:

run_function = lambda x, y: x if y in x else x + [y]

​ 该 lambda 函数接收两个参数 x 和 y,其中 x 是经过比对后已经保留的元素,y 是需要比对的新元素。该函数的主要功能是:如果 y 在 x 中,则直接返回 x,否则将 y 添加到 x 中。这个过程通过条件表达式 x if y in x else x + [y] 来实现。

​ 该 lambda 函数接收两个参数 x 和 y,其中 x 是经过比对后已经保留的元素,y 是需要比对的新元素。该函数的主要功能是:如果 y 在 x 中,则直接返回 x,否则将 y 添加到 x 中。这个过程通过条件表达式 x if y in x else x + [y] 来实现。

​ 函数中利用 reduce() 函数和 lambda 表达式对列表中的元素进行迭代处理,保留不重复的元素:

return reduce(run_function, [[],] + data_list)

reduce() 函数的第一个参数是一个函数对象,第二个参数是一个迭代器对象。迭代器对象的第一个元素是一个空列表,表示初始状态。列表 data_list 中的每个元素都会依次作为参数传递给 run_function 函数进行比对和过滤。最终返回的是一个去重后的列表,其中包含了原列表中的所有元素,但不包含重复的元素。

问题

​ 当数据量过大时,这段代码可能会运行贼慢。原因是因为它使用了两个嵌套的循环,其中包含了一些操作,这些操作在大量数据的情况下会变得非常耗时。
​ 如下图,是这个代码处理我的数据集时所用的时间

在这里插入图片描述

​ 这段代码没有显式使用两个嵌套的循环,但是使用了reduce函数,reduce函数本质上是一个迭代器,每次遍历数据集中的一个元素,而这里的数据集是一个列表,所以每次遍历的元素是一个字典。

​ 在reduce函数的运行过程中,使用了lambda函数作为参数,这个lambda函数中又使用了in关键字来判断一个元素是否在列表中已经出现过,这里的判断操作会导致内部的嵌套循环。因此,虽然没有显式使用两个嵌套的循环,但实际上reduce函数内部实现了两层循环,所以当数据集过大时,程序的运行速度会变得非常慢。

总结

reduce函数的运行过程中,使用了lambda函数作为参数,这个lambda函数中又使用了in关键字来判断一个元素是否在列表中已经出现过,这里的判断操作会导致内部的嵌套循环。因此,虽然没有显式使用两个嵌套的循环,但实际上reduce函数内部实现了两层循环,所以当数据集过大时,程序的运行速度会变得非常慢。

总结

在编写代码时,最好避免使用嵌套循环从而造成大量数据集的笛卡儿积

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/522003.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

华为OD机试真题 Java 实现【相同数字的积木游戏1】【2023Q2 100分】

一、题目描述 小华和小薇一起通过玩积木游戏学习数学。 他们有很多积木,每个积木块上都有一个数字,积木块上的数字可能相同。 小华随机拿一些积木挨着排成一排,请小薇找到这排积木中数字相同且所处位置最远的2块积木块,计算他们…

【C++】——string的模拟实现

前言: 在之前的学习中,我们已经对string类进行了简单的介绍,大家只要能够正常使用即可。但是在面试中,面试官总喜欢让学生自己 来模拟实现string类,最主要是实现string类的构造、拷贝构造、赋值运算符重载以及析构函数…

lightroom磨皮滤镜中文插件Portraiture4最新版本

哈喽!小伙伴们!整个摄影后期行业都在用Portraiture,这是一个被奉为高级磨皮面板,修图神器、修图的的扩展面板!Portraiture这款磨皮插件终于更新啦!最近推出了Portraiture4.03版本,新版本光影处理更强大&…

《编程思维与实践》1066.最小不重复数

《编程思维与实践》1066.最小不重复数 题目 思路 一般在oj上循环 2 ⋅ 1 0 9 2\cdot 10^9 2⋅109次以上就会超时,所以由于这题的数据A可以很大,直接循环加一再判断会超时. 优化:首先可以明确要想使不重复数尽可能小,则高位数字应该尽可能小, 即先找到最靠前的两个重复数字,然后…

【Vector VN1630/40 I/O应用】-1-简易示波器

案例背景(共13页精简):该篇博客将告诉您: Vector VN1630A,VN1640A,VH6501 I/O的使用;将Vector VN1630A/VN1640A CAN/LIN Interface的I/O接口充当一个简易的“示波器”使用;观察“CAN唤醒”工作的ECU控制器…

关于C语言的杂记4

文章目录 数据与程序结构C语言的编程机制#include <>和#include ""的区别形式参数和实际参数值传递地址传递 素数 文章内容摘自或加工于C技能树一些大佬的博文 数据与程序结构 阅读完C的编程机制和函数的声明和定义后的一些启发。——预处理 C语言的编程机制 …

dubbo技术

1、Dubbo的前世今生 2011年10月27日&#xff0c;阿里巴巴开源了自己的SOA服务化治理方案的核心框架Dubbo&#xff0c;服务治理和SOA的设计理念开始逐渐在国内软件行业中落地&#xff0c;并被广泛应用。 早期版本的dubbo遵循SOA的思想&#xff0c;是面向服务架构的重要组件。 …

1708_Simulink中取数组元素

全部学习汇总&#xff1a; GitHub - GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes…

【多线程】线程安全问题原因与解决方案

目录 线程安全的概念 线程不安全示例 线程不安全的原因 多个线程修改了同一个变量 线程是抢占式执行的 原子性 内存可见性 有序性 线程不安全解决办法 synchronized 关键字-监视器锁monitor lock synchronized 的特性 互斥 刷新内存 可重入 synchronized 使用示例 Java 标…

【第三章:存储系统】

目录 知识框架No.0 引言No.1 存储器概述No.2 主存储器一、SRAM芯片和DRAM芯片二、只读存储器三、主存储器的基本组成1、基本的半导体元件和原理 知识框架 No.0 引言 这一章节主要是&#xff1a;这些二进制的数据在计算机内部如何存储 在学习这个章节之前&#xff0c;首先把下面…

Mybatis - 基础

文章目录 一、 Mybatis基本介绍二、 Mybatis 快速入门程序2.1 引入Mybatis依赖2.2 准备工作2.3 配置SQL信息2.3.1 IDEA连接数据库2.3.2 打开日志信息 2.4 JDBC 了解2.5 数据库连接池2.5.1 Druid数据库连接池 三、 Mybatis 基础3.1 环境准备3.1.1 数据库表3.1.2 实体类 3.2 基础…

EasyRecovery16中文最新版电脑数据恢复软件下载使用教程

EasyRecovery如果需要使用它来恢复数据&#xff0c;请注意&#xff0c;尤其是当需要恢复的数据文件非常重要时&#xff0c;建议使用软件EasyRecovery以保障数据安全。共有三个版本&#xff0c;分别是个人版、专业版、企业版&#xff0c;这三种都可以免费下载并使用&#xff0c;…

[MySQL]关于MySQL索引的一点点东西

最是人间留不住,朱颜辞镜花辞树. 目录 一.为什么需要索引 1.什么是索引 2.索引的创建原则 二.理解索引 1. MySQL与磁盘交互基本单位 2.索引的结构 a.关于hash索引,B树索引,B树索引的特点 B树 B树 HASH b.为什么使用InnoDB 存储引…

15-721 chapter 13 查询执行

优化的目标 CPU层面 cpu是多级流水线操作&#xff0c;所以我们的目标是让每个处理器的每个部分都处于busy。多条流水线&#xff0c;我们没有依赖的指令可以放到不同的流水线里面。但是流水线如果遇到branch判断错误的话&#xff0c;就要flush掉 可以用值传递来代替跳转 查询执…

Linux开发板安装Python环境

1. 环境介绍 硬件&#xff1a;STM32MP157&#xff0c;使用的是野火出的开发板。 软件&#xff1a;Debian ARM 架构制作的 Linux 发行版&#xff0c;版本信息如下&#xff1a; Linux发行版本&#xff1a;Debian GNU/Linux 10 内核版本&#xff1a;4.19.94 2. Python 简介…

基于常用设计模式的业务框架

前言 做开发也有好几年时间了&#xff0c;最近总结和梳理自己在工作中遇到的一些问题&#xff0c;工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的&#xff0c;也意味着经过很多开发人员之手&#xff0c;最后到你这里&#xff0c;大部…

每日学术速递5.11

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.Diffusion Explainer: Visual Explanation for Text-to-image Stable Diffusion 标题&#xff1a;扩散解释器&#xff1a;文本到图像稳定扩散的视觉解释 作者&#xff1a;Seongmin…

【数据结构】【算法】二叉树、二叉排序树、树的相关操作

树结构是以分支关系定义的一种层次结构&#xff0c;应用树结构组织起来的数据&#xff0c;逻辑上都具有明显的层次关系。 操作系统中的文件管理系统、网络系统中的域名管理、数据库系统中的索引管理等都使用了树结构来组织和管理数据。 树的基本概念 树Tree是由n个节点组成的有…

数据结构-查找-散列结构(散列表)

目录 *一、散列表 二、散列函数 *除留余数法 *直接定址法 数字分析法 平方取中法 三、冲突处理方法--开发定地法 *3.1线性探测法 *查找效率&#xff1a; *3.2平方探测法 3.3伪随机序列法 3.4再散列法 *一、散列表 又称哈希表&#xff0c;数据元素的关键字与其存储…

bgp团体属性配置案例一

RouterA的配置 sysname RouterA interface GigabitEthernet1/0/0 ip address 192.168.0.1 255.255.255.0 interface LoopBack0 ip address 1.1.1.1 255.255.255.255 bgp 10 router-id 1.1.1.1 //Router ID&#xff0c;建议配置为LoopBack0的IP地址 peer 192.168.0.2 as-number …