Python---set()集合去重底层逻辑

背景

在做数据清洗的时候,想要实现一个程序,去除数据集里面相同的图片。那么我很快就想到了用set()去对数据进行一个过滤,那么怎么实现呢?

我的实现思路

class Img:
    def __init__(self, img, file_name):
        self.img = img
        self.file = file_name

    def __eq__(self, other):
        print("进入相等判断")
        if self.img.shape != other.img.shape:
        # 如果图片shape都不一样 那肯定不一样
            return False
        return np.array_equal(self.img, other.img)

    def __str__(self):
        return "-- "+str(self.file)+" --"

    def __hash__(self):
        a, b, c = self.img.shape
        self.hash = hash(a)+hash(b)+hash(c)
        return hash(a)+hash(b)+hash(c)

def demo1():
    # set 是先用 __hash__ 如果hash相等 那么再用__eq__比较
    array1 = np.random.rand(*(1, 2, 3))  # 生成0到1之间的随机浮点数
    array2 = np.random.randint(0, 10, size=(1,2,3))  # 生成0到9之间的随机整数
    # 用两个数组来模拟图片
    img1 = Img(array1, "1")
    img2 = Img(array2, "2")
    print(img1.img.all() == img2.img.all())
    fina = set()
    fina.add(img1)
    fina.add(img2)
    for i in fina:
        print(i)
    print(img1.hash == img2.hash)

首先,构建一个Img类,里面有图片的np数组和图片的文件名。然后,再写一个测试函数demo1。在测试函数里面,我用两个shape一样的随机数组来代替两张长,宽,颜色通道一样但内容不一样的图片。最后运行demo1,输出如下。

False
进入相等判断
-- 1 --
-- 2 --
True
# 这个结果说明了 两个对象的hash值是一样的
# set调用了元素类的__eq__方法进行比较发现这两个元素是不一样的
# 上面的现象好像说明了
# set是先用元素类的__hash__方法进行去重
# 如果元素的hash值相同再用元素的__eq__方法去重

为了保险我们再写个demo2测试函数。

def demo2():
    # set 是先用 __hash__ 如果hash相等 那么再用__eq__比较
    array1 = np.random.rand(*(1, 2, 3))  # 生成0到1之间的随机浮点数
    array2 = np.random.randint(0, 9, size=(3,2,3))  # 生成0到9之间的随机整数
    print(array2.all() == array1.all())
    # 用两个数组来模拟图片
    img1 = Img(array1, "1")
    img2 = Img(array2, "2")
    print(img1.img.all() == img2.img.all())
    fina = set()
    fina.add(img1)
    fina.add(img2)
    for i in fina:
        print(i)
    print(img1.hash == img2.hash)

输出结果为以下,这就更说明了,set的去重逻辑,如果集合元素里面的hash值不一样的话,那么这两个元素就不一样,否则进行__eq__方法的比较。

False
-- 2 --
-- 1 --
False

set()集合去重底层逻辑

set的去重是通过两个函数__hash__和__eq__结合实现的。当两个变量的哈希值不相同时,就认为这两个变量是不同的;当两个变量哈希值一样时,调用__eq__方法,当返回值为True时认为这两个变量是同一个,应该去除一个。返回FALSE时,不去重。

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HUTAC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值