python set()去重的底层原理及实例
作者:哟,写bug呢?? 发布时间:2021-08-30 05:04:11
set是什么?
数学上,把set称做由不同的元素组成的集合,集合(set)的成员通常被称做集合元素(set elements)。Python把这个概念引入到它的集合类型对象里。集合对象是一组无序排列的可哈希的值。集合关系测试和union、intersection等操作符在Python里也同样如我们所预想地那样工作。
set特点
集合的元素有三个特征:
1.确定性:集合中的元素必须是确定的;
2.互异性:集合中的元素互不相同,如:集合A={1,a},则a不能等于1);
3.无序性:集合中的元素没有先后之分,如:{3,4,5}和{3,5,4}算作同一个集合。
python中集合(set)是一个无序不重复元素的集,基本功能包括关系测试和消除重复元素,还可以计算交集、差集、并集等,它与列表(list)的行为类似,区别在于set不同包括重复的值,而且set元素是无序的。
在python中可以用大括号 {} 创建集合。注意:如果要创建或初始化一个空集合,你必须用 set() 而不是 {} 。因为后者{} 作为创建一个空的字典,以后我们会介绍字典这种数据结构。
一、set去重简单实例
ls = [1,2,3,1,2]
print(set(ls))
我们知道对于一个列表最简单的去重方法就是直接调用set函数,利用集合元素的唯一性,就可以做到去重。但是,这个底层原理究竟是什么样的却一直半解。
且看下面剖析
二、重新set实现机制
class Foo:
def __init__(self,name,count):
self.name = name
self.count = count
def __hash__(self):
print("%s调用了哈希方法"%self.name)
return hash(id(self))
def __eq__(self, other):
print("%s调用了eq方法")
if self.__dict__ == other.__dict__:
return True
else:return False
f1 = Foo('f1',1)
f2 = Foo('f2',2)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))
从上面可以看出,set方法就是去调用hash方法,然后根据哈希值一不一样就行去重判断,但是事实就是样吗?且看下面程序。
class Foo:
def __init__(self,name,count):
self.name = name
self.count = count
def __hash__(self):
print("%s调用了哈希方法"%self.name)
return hash(self.count)
def __eq__(self, other):
print("%s调用了eq方法"%self.name)
return self.__dict__ == other.__dict__
f1 = Foo('f1',1)
f2 = Foo('f2',1)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))
我看可以看出,实际上f1,f3的哈希值是相等的,但是set并没有这么简单就判断f1,f3是重复的,而是进一步通过eq方法判断这两个值是否相等,只有相等时才会认为这两个之间实际上是同一个。为了验证上面的说法,我们来看看下面的代码。
f1 = Foo('f1',1)
f2 = Foo('f1',1)
f3 = Foo('f3',3)
ls = [f1,f2,f3]
print(set(ls))
可以看出去重后,只有两个元素,所以上面说法得证。
三、结论
set的去重是通过两个函数__hash__和__eq__结合实现的。
1、当两个变量的哈希值不相同时,就认为这两个变量是不同的
2、当两个变量哈希值一样时,调用__eq__方法,当返回值为True时认为这两个变量是同一个,应该去除一个。返回FALSE时,不去重
四、应用场景需求
有一个公司,现有100个员工,由于数据库不完善,使用时间比较长,里面有很多重复数据需要清除。具体需求如下:
每个员工的属性有:姓名,性别,年龄,部门。 由于年龄和部门都会发生变化,所以现在认为只要两个员工之间姓名和性别一样,就认为是同一个人。
请实现员工去重:
class Staff:
def __init__(self,name,gender,age,department):
self.name = name
self.gender = gender
self.age = age
self.department = department
def __hash__(self):
return hash(self.name+self.gender)
def __eq__(self, other):
return True
ls = ['zs','ls','ww','zq']
gender_list = ['man','femal']
staff_list = []
for i in range(100):
staff_list.append(Staff(ls[i%4],gender_list[i%2],i,'class'))
print(set(staff_list))
print([(i.name,i.gender) for i in set(staff_list)])
来源:https://www.cnblogs.com/linshuhui/p/9580620.html
猜你喜欢
- 最近在学习Python网络相关编程,这个代码实现了Telnet自动连接检测root用户密码,密码取自密码本,一个一个检测密码是否匹配,直到匹
- 手动安装Anaconda环境变量安装 Anaconda后,在命令行执行python命令或conda命令会报错无法找到此时就需要我们手动添加环
- 关于oracle 优化的内容很多,概念庞杂,不过可以总结出一个大纲性的东西作为需要考虑的方向,然后再逐步细化。oracle优化按重要性需要考
- 前言可选链操作符(?.)允许读取位于链接对象链身处的属性的值,而不必明确验证链中的每个引用是否有效。不同之处在于,在引用为空(null或者u
- 前言项目中要实现多选,就想到用插件,选择了bootstrap-select。附上官网api链接,http://silviomoreto.gi
- 写程序的人在编写由asp页面生成静态页面html的时候,如果同时生成大量页面,一定遇到过浏览器下方的进度条上显示着3%,6%,10%等缓慢增
- 正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自
- pytorch中的transforms模块中包含了很多种对图像数据进行变换的函数,这些都是在我们进行图像数据读入步骤中必不可少的,下面我们讲
- 在当前的Web设计中,jQuery被越来越多地应用在Web开发中,之所以jQuery收到如此程度的欢迎,除了其本身具备的优秀易读易操作的代码
- 使用python批量修改文本文件编码格式把文本文件的编码格式进行批量幻化,比如ascii, gb2312, utf8等,相互转化,字符集的大
- 目录一、简单字段定义1、定义 Schema 并生成 Parquet 文件2、验证 Parquet 数据文件二、含嵌套字段定义1、验证 Par
- 在写代码时,经常会遇到多个矩阵数组拼接的情况,numpy里dstack, hstack, vstack, 都有拼接的作用,那么这些函数是怎么
- 本文实例讲述了Python2与Python3的区别。分享给大家供大家参考,具体如下:python2与python3的区别1、性能2、编码格式
- 本文实例为大家分享了tensorflow实现线性回归的具体代码,供大家参考,具体内容如下一、随机生成1000个点,分布在y=0.1x+0.3
- 下面是一份在 HTML 4 Strict 和 XHTML 1.0 Strict 下必须遵守的标签嵌套规则,比如你不能在 <a>
- 今天我们将介绍处理大量数据时非常方便的工具。我不会只告诉您可能在手册中找到的一般信息,而是分享一些我发现的小技巧,例如tqdm与 multi
- 我们经常见到很多网站留言系统的显示访客的IP地址都是隐藏了一部分,以达到隐蔽访客真实地理位置的功能。如:111.222.333.*,当然在系
- 本文实例讲述了Python实现的直接插入排序算法。分享给大家供大家参考,具体如下:# -*- coding:utf-8 -*-'
- 本文是基于上一篇(python项目:学生信息管理系统(初版) )进行了完善,并添加了新的功能。主要包括有:完善部分:输入错误;无数据查询等异
- 标准库Python拥有一个强大的标准库。Python语言的核心只包含数字、字符串、列表、字典、文件等常见类型和函数,而由Python标准库提