在上篇文章《雜湊值和可變性hash value and mutability》最後說到set去重問題,所以這篇主要是通過實踐來研究一下set去重背後的故事,當然也是參考了網上一些資料得到了一些啟發,感謝那些陌生的喜歡分享的博友們。
set的簡單應用
利用set中元素的唯一性,我們可以對list去重
list1 = [1,2,3,1,2,3]
print(set(list1))
# output:
set去重的原理
set中元素的hash值不一樣
class person:
def __init__(self, name, identityid):
self.name = name
self.identityid = identityid
def __hash__(self):
print("%s call hash method"%self.name)
return hash(id(self))
def __eq__(self, other):
print("%s call eq method"%self.name)
if self.__dict__ == other.__dict__:
return true
else:
return false
p1 = person('p1', 123456789)
p2 = person('p2', 123456789)
print("p1 id: %s"%hex(id(p1)))
print("p2 id: %s"%hex(id(p2)))
list_test = [p1,p2]
print(set(list_test))
可以看出set呼叫了元素的hash方法,p1和p2的hash返回不同,就認為是不重複的元素,所以不去重
#output:
p1 id: 0x209563fabe0
p2 id: 0x209563fa910
p1 call hash method
p2 call hash method
set中元素的hash返回值是一樣的
class person:
def __init__(self, instance, name, identityid):
self.instance = instance
self.name = name
self.identityid = identityid
def __hash__(self):
print("%s call hash method"%self.instance)
return hash(self.identityid)
def __eq__(self, other):
print(f" call eq method: equal to ")
if self.name == other.name:
return true
else:
return false
p1 = person('p1','kelly', 123456789)
p2 = person('p2','xia', 123456789)
p3 = person('p3','peter', 111111111)
p4 = person('p4','kelly', 123456789)
p5 = person('p5','kelly.xia', 123456789)
print("p1 id: %s"%hex(id(p1)))
print("p2 id: %s"%hex(id(p2)))
print("p3 id: %s"%hex(id(p3)))
print("p4 id: %s"%hex(id(p4)))
print("p5 id: %s"%hex(id(p5)))
print(f"p1==p4:")
list_test = [p1,p2,p3,p4,p5]
print(set(list_test))
p1,p2,p3,p4,p5,通過id來看是指向不同的引用的,p1和p2的hash返回值相同,所以再呼叫p1的eq方法,eq返回是false的,所以認為p1和p2是不重複的。而p1和p4,hash返回值是一樣的,再使用者p1的eq方法,返回是ture,所以認為p1和p4是重複的,將除去p4.最後的p5,跟p1,p2的hash返回值都是一樣的,所以再分別呼叫p1和p2的eq方法,因為eq訪求返回都為false,所以認為p5分別和p1,p2是不重複的。
#output:
p1 id: 0x209564e1fd0
p2 id: 0x209564e1070
p3 id: 0x209564e1ac0
p4 id: 0x209564e1430
p5 id: 0x209564e1c40
p1 call eq method: equal to p4
p1==p4:true
p1 call hash method
p2 call hash method
p1 call eq method: equal to p2
p3 call hash method
p4 call hash method
p1 call eq method: equal to p4
p5 call hash method
p1 call eq method: equal to p5
p2 call eq method: equal to p5
結論由以上得出結論:set的去重是通過兩個函式__hash__和__eq__結合實現的。當兩個物件的雜湊值不相同時,就認為這兩個物件是不同的; 當兩個物件的雜湊值一樣時,呼叫__eq__方法,當返回值為true時認為這兩個物件是重複的,應該去除乙個。返回false時,認為這兩個物件不是重複的,所以不去重。
應用利用set去重特性,我們擴充套件思維應用到許多需要去重的場景中去,關鍵就是override超類object的__hash__和__eq__方法。
set 去重原理
眾所周知,set 是 python 中的 天然去重因子 對一串資料如 lyst 1,1,2,4,4 我們常常 set 一下,也就是 set lyst 達到去重目的。那麼,set 是如何去重的呢?為了貼合實際的開發需求,我們常需要自定義資料結構。拿通用示例 student 來說。class stude...
陣列去重 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沒...