python的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方法,然后根据哈希值一不一样就行去重判断,但是事实就是样吗?且看下面程序。

'''

遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939

寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!

'''

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个员工,由于数据库不完善,使用时间比较长,里面有很多重复数据需要清除。具体需求如下:

每个员工的属性有:姓名,性别,年龄,部门。 由于年龄和部门都会发生变化,所以现在认为只要两个员工之间姓名和性别一样,就认为是同一个人。

请实现员工去重:

'''

遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939

寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!

'''

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)])

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值