眾所周知,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沒...