2017-04-05 90 views
1

當我運行這行代碼,我不明白爲什麼這兩個lists相等,但是來自同一列表中創建sets異常行爲

class Field(object): 
    def __init__(self, fieldnames): 
     self.name = fieldnames[0] 
     self.alias = frozenset(fieldnames) 

    def __eq__(self, other): 
     if not isinstance(other, Field): 
      return False 
     return len(self.alias & other.alias) >= 1 

    def __hash__(self): 
     return hash(self.name) 

    def __str__(self): 
     return "{field_name: %s}" % self.name 

    def __repr__(self): 
     return "<Field: (%s: %r)" %(self.name, self.alias) 

In [185]: field_list1 = [["Field 1"], ["Field 2"], ["Field 3"]] 

In [186]: field_list2 = [["Field 1"], ["Field 21", "Field 2"], ["Field 3"]] 

In [187]: field1 = [Field(f) for f in field_list1] 

In [188]: field2 = [Field(f) for f in field_list2] 

In [189]: field1 == field2 
Out[189]: True 

In [190]: set(field1) == set(field2) 
Out[190]: False 

據對集Python文檔如果第一組的每個元素都在第二組中,則兩組相等,反之亦然。按照這個定義,這兩個集合應該是平等的,但我不確定它們爲什麼不是。

因此,我想知道這種行爲背後的原因?

+1

什麼是'd'和'e'?你是不是指'field_list1'和'field_list2'? –

+1

'field1'具有''Field 1「,」Field 2「,」Field 3「'作爲'Field'對象的'name'屬性。但是field2有''Field 1','Field 21','Field 3''。那些不一樣。 –

+0

如果您想查找彼此的別名的可傳遞字段組,可以考慮使用[union-find或disjoint set algorithm](https://en.wikipedia.org/wiki/Disjoint-set_data_structure)。 –

回答

3

你有不同的比較在這裏進行。

比較兩個列表時,通過==將第一個列表中的每個元素與另一個列表中的等效元素進行比較,該程序調用eq方法。雖然你的代碼很奇怪(爲什麼不只是len(self.alias) == len(other.alias)?),它會根據別名屬性的相對大小產生True或False。

但是設置完全不同。比較是通過哈希來完成的,而不是通過平等進行;你已經定義了你的__hash__方法根據名稱而不是別名返回不同的結果。

1

field1 == field2進行使用== oprerator(通過調用__eq__)項兩比較。

set(field1) == set(field2)檢查是否所有元素都在兩組中。集合中的元素由它們的哈希標識。你從名字計算散列。列表中的某些元素具有不同的名稱,因此它們是不同的集合元素。

print(field1[1].name) # 'Field 2' 
print(field2[1].name) # 'Field 21' 

綜上所述,列表比較是基於__eq__但設置比較是基於__hash__。它們基於Field課程中完全不同的計算,因此您會得到不同的結果。