set 去重原理

2021-09-24 10:36:04 字數 3498 閱讀 1964

眾所周知,set() 是 python 中的"天然去重因子"。對一串資料如:lyst = [1, 1, 2, 4, 4],我們常常 set 一下,也就是:set(lyst),達到去重目的。

那麼,set() 是如何去重的呢?

為了貼合實際的開發需求,我們常需要自定義資料結構。拿通用示例 student 來說。

class

student

(object):

def__init__

(self, name, age, sid)

: self.name = name

self.age = age

self.sid = sid

現在,我們例項兩個 student 物件,分別是 stu1 和 stu2,其名字 name,年齡 age,學號 sid 相同。現實生活中,可以認為這兩個學生是同一人。

stu1 = student(

"zhong",15

,11198

)stu2 = student(

"zhong",15

,11198

)print

(set

([stu1, stu2]))

# 輸出:

然而 set() 並不這樣認為,因此沒有實現去重效果。

事實上,我們用比較操作符==會發現,python 直譯器認為 stu1 並不等於 stu2。

print

(stu1 == stu2)

# 輸出:false

會有上述現象,是因為程式沒有按照現實需求執行。現實需求是:如果名字、年齡、學號都相同,那一定就是同乙個人,因而我們需要重寫魔法方法__eq__()。**如下所示:

class

student

(object):

def__init__

(self, name, age, sid)

: self.name = name

self.age = age

self.sid = sid

def__eq__

(self, other)

:return self.name == other.name and \

self.age == other.age and \

self.sid == other.sid

stu1 = student(

"zhong",15

,11198

)stu2 = student(

"zhong",15

,11198

)print

(stu1 == stu2)

# 輸出:true

現在我們是不是可以用 set 去重了呢?

print

(set

([stu1, stu2]))

----

----

----

----

----

----

----

----

-traceback (most recent call last)

: file "*********"

, line 18,in

print

(set

([stu1, stu2]))

typeerror: unhashable type

:'student'

很遺憾,直譯器報錯了。它說 student 型別的物件不能雜湊。

當我們沒有為 student 新增__eq__()函式時,set() 還不會報錯,現在卻說不能雜湊?好在,我們可以重寫__hash__()方法,改變原來的預設的雜湊處理邏輯。

class

student

(object):

def__init__

(self, name, age, sid)

: self.name = name

self.age = age

self.sid = sid

def__eq__

(self, other)

:return self.name == other.name and \

self.age == other.age and \

self.sid == other.sid

def__hash__

(self)

:return

hash

((self.name, self.age, self.sid)

)stu1 = student(

"zhong",15

,11198

)stu2 = student(

"zhong",15

,11198

)print

(set

([stu1, stu2]))

# 輸出:

為方便起見,這裡借助了 tuple 的不可變特性,使其能夠正確通過雜湊處理。此時我們再用 set() 去重,發現成功了!

倘若在上述**的基礎上,試圖把 eq 函式去掉,你會發現 set() 去重失效了。儘管它們的雜湊結果相同。

class

student

(object):

def__init__

(self, name, age, sid)

: self.name = name

self.age = age

self.sid = sid

def__hash__

(self)

:return

hash

((self.name, self.age, self.sid)

)stu1 = student(

"zhong",15

,11198

)stu2 = student(

"zhong",15

,11198

)print

(set

([stu1, stu2]))

# 輸出:

print

(hash

(stu1)

==hash

(stu2)

)# 輸出: true

經過前面一步步推導,我們也得出了 set() 去重原理:

set() 函式中會先呼叫物件的__hash__()方法,獲取 hash 結果;

如果 hash 結果相同,用比較操作符==(也就是呼叫函式__eq__())判斷二者的值是否相等;

如果都相等,去重;否則,set() 認為二者不同,兩個都保留到結果中。

python的set去重原理 Set去重原理

在上篇文章 雜湊值和可變性hash value and mutability 最後說到set去重問題,所以這篇主要是通過實踐來研究一下set去重背後的故事,當然也是參考了網上一些資料得到了一些啟發,感謝那些陌生的喜歡分享的博友們。set的簡單應用 利用set中元素的唯一性,我們可以對list去重 l...

陣列去重 Set

常見的陣列去重方法大多考慮遍歷 indexof,例如 var arr1 1 2,3 4,5 6,6 6 function unique arr return newarr unique arr1 1,2,3,4,5,6 但是es6引入了新的資料結構set,可以直接實現陣列去重 甚至也可以用於字串去重...

set 的方法以及set 去重

set 迴圈的時候,key 和value的值是一樣的 建立 let setarr new set 增 setarr.add 1,2,3,1 2 3 console.log setarr.size 6 刪 set.clear 減 set.delete 1 查 set.has 1 true 1 set沒...