8

次のようなデータ構造 ( Hash) があります。

{
    foo: "Test string",
    bar: [475934759, 5619827847]
}

Hash将来的に等しいかどうかをチェックするために、そこからチェックサムを作成しようとしています。hashのメソッドを使用してみHashました。満足のいく見栄えの良いハッシュが得られましたがHash、インタープリターを再起動すると、同じハッシュが別のハッシュを生成することがわかりました。

HashStringまたはArrayインスタンスから〜128ビットのチェックサムを作成できるようにしたいだけです。

これは可能ですか?

4

3 に答える 3

7

オブジェクトのMarshal ダンプまたはJSON表現に基づいて、独自のハッシュを計算できます。

これは、Marshal ダンプの MD5 ハッシュを計算します。

require 'digest/md5'

hash = {
  foo: "Test string",
  bar: [475934759, 5619827847]
}

Marshal::dump(hash)
#=> "\x04\b{\a:\bfooI\"\x10Test string\x06:\x06ET:\bbar[\ai\x04'0^\x1Cl+\b\x87\xC4\xF7N\x01\x00"

Digest::MD5.hexdigest(Marshal::dump(hash))
#=> "1b6308abdd8f5f6290e2825a078a1a02"

アップデート

コア機能を変更することはお勧めしませんが、独自の戦略を実装できます。

class Hash
  def _dump(depth)
    # this doesn't cause a recursion because sort returns an array
    Marshal::dump(self.sort, depth)
  end

  def self._load(marshaled_hash)
    Hash[Marshal::load(marshaled_hash)]
  end
end

Marshal::dump({foo:1, bar:2})
#=> "\x04\bu:\tHash\e\x04\b[\a[\a:\bbari\a[\a:\bfooi\x06"

Marshal::dump({bar:2, foo:1})
#=> "\x04\bu:\tHash\e\x04\b[\a[\a:\bbari\a[\a:\bfooi\x06"

Marshal::load(Marshal::dump({foo:1, bar:2}))
#=> {:bar=>2, :foo=>1}
于 2013-10-15T11:56:29.323 に答える
2

上記の@Stefanの回答に基づいて構築するには、ハッシュの順序が重要な場合は、Mashallを介してプッシュする前に出力をソートしてください。

require 'digest/md5'

hash = {
  'foo'=> "Test string",
  'bar'=> [475934759, 5619827847]
}

puts Digest::MD5.hexdigest(Marshal::dump(hash.collect{|k,v| [k,v]}.sort{|a,b| a[0] <=> b[0]})) 
# 8509c564c0ae8dcb6c2b9b564ba6a03f

hash = {
  'bar'=> [475934759, 5619827847],
  'foo'=> "Test string"
}

puts Digest::MD5.hexdigest(Marshal::dump(hash.collect{|k,v| [k,v]}.sort{|a,b| a[0] <=> b[0]})) 
# 8509c564c0ae8dcb6c2b9b564ba6a03f 
于 2013-10-15T12:29:48.750 に答える