2014-11-02 58 views
2

所以我有一個類,其中我需要重寫相等運算符。這並不難。但是除非my_obj.hash對於兩個正在比較的對象是相等的,否則不會使用自定義相等運算符。所以我們需要重寫散列()在Ruby中製作對象哈希的最佳方法是什麼?

我有點卡住最好的方式來做到這一點。我的對象嵌入了另外三個對象實例。我的例子中看到,對於簡單的實例瓦爾你可以只取瓦爾的哈希自己:

[var1, var2, var3].hash 

更具體地說,我班有實例瓦爾三個嵌入對象,我們姑且稱之爲:

一個 B1 B2

我的對象的

兩個實例是相等如果

object1.B1 == object2.B1 && object1.B2 == object2.B2 || 
     object1.B1 == object2.B2 && object1.B2 == object2.B1 

在換句話說,COLLEC無論分配給哪個特定的變量,B1和B2都有相同的兩個對象。

B1和B2也有自定義等式機制。

我只是不清楚重寫hash()的最佳策略。

對不起,如果這個例子是抽象的,我試圖避免發佈很多代碼。

回答

2

嘗試使用Set而不是數組,因此順序無關緊要。你必須有這條線在頂部:

require 'set' 

然後讓含有對象集,並用它來幫助實現平等的經營者和哈希方法。我假設Set#散列行爲正確,你可以在你的散列方法中使用它。設置#==可以用來簡化您的相等運算符。

http://www.ruby-doc.org/stdlib-2.1.4/libdoc/set/rdoc/Set.html

+1

如果'B1'和'B2'是不可取的,我支持這種技術。你的'hash'方法就像'return Set [self.B1,self.B2] .hash'一樣簡單。 – 2014-11-02 02:01:16

-1

我假設散列值可以是任何對象,只要它在您的案例中的每個對象中都是唯一的。如果這種假設是正確的,那麼定義對象hash()方法如何返回爲數組,例如?

我不是100%清楚你想達到什麼。但我已經解釋了self.B1self.B2的順序沒有關係。那麼這是一個可能性:

def hash 
    [self.B1.hash, self.B2.hash].sort 
end 

然後,你可以比較兩個對象的hash()

(my_obj1.hash == my_obj2.hash) 
+2

-1。這嚴重違反了'hash'的合同。 'hash'指定返回一個'Integer'。 – 2014-11-02 01:52:05

+0

@JörgWMittag什麼是「合同」?默認情況下,'hash()'返回Integer。所以,我同意任何通用庫'hash()'必須返回Integer。但是當無論如何都試圖重新實現'hash()'時,我只是認爲可以修改它,只要它在框架內一致。如果他/她不喜歡它,那麼他/他不會選擇它。 – 2014-11-02 02:07:31

+2

合約是'hash' a)返回符合'to_int'約定的東西,b)兩個相等的對象具有相同的'hash'值。您的執行違反了a)點,例如導致如下:'{StevesClass.new => nil}#TypeError:沒有將數組隱式轉換爲整數。 '[StevesClass.new,StevesClass.new] .uniq#TypeError:沒有將數組隱式轉換爲Integer'。 '[StevesClass.new,StevesClass.new] .hash#TypeError:沒有將數組隱式轉換爲Integer'。 '需要'設置';設置[StevesClass.new,StevesClass.new]#TypeError:...'。 – 2014-11-02 03:13:54

1

是你的B1B2對象排序?如果是這樣,這裏是一個很容易實現的hash方法:

class MyClass 
    def hash 
    return [self.B1, self.B2].sort.hash 
    end 
end 

如果他們目前沒有排序,它是沒有意義的任何內在價值對它們進行排序,你可以永遠只是排序object_id

class BClass 
    include Comparable 

    def <=> (other) 
    case other 
    when BClass then return (self.object_id <=> other.object_id) 
    else return nil 
    end 
    end 
end 

這使您B1B2對象自己解決與對方,而扔「引發ArgumentError:與Y X的比較失敗」與任何其他類的實例。

如果你打算使用object_id的路線,雖然,它可能是更容易使用,開始與實現你hash方法:

class MyClass 
    def hash 
    return [self.B1.object_id, self.B2.object_id].sort.hash 
    end 
end 

,但是這將意味着只有自相同的對象會正確地變得平等,而不僅僅是「看起來」相似的物體。要理解我的意思,請比較以下內容:

# Comparison of look-alike objects 
"a".object_id == "a".object_id # => false 

# Comparison of self-same objects 
a = "a" 
a.object_id == a.object_id  # => true 
+0

你是我最喜歡的Rubyist之一.. – 2014-11-02 12:03:27

相關問題