对于缓存层,我需要为哈希创建一个唯一的sha。它对于该哈希的内容应该是唯一的。具有相同配置的两个哈希应具有相同的sha。
in_2014 = { scopes: [1, 2, 3], year: 2014 }
not_in_2104 = { scopes: [1, 2, 3], year: 2015 }
also_in_2014 = { year: 2014, scopes: [1, 2, 3] }
in_2014 == also_in_2014 #=> true
not_in_2104 == in_2014 #=> false
现在,为了存储它并快速查看,需要转动它 进入一个shasum的东西。简单地转换为字符串不起作用, 所以从中生成hexdigest也不起作用:
require 'digest'
in_2014.to_s == also_in_2014.to_s #=> false
Digest::SHA2.hexdigest(in_2014.to_s) == Digest::SHA2.hexdigest(also_in_2014.to_s) #=> false
我想要的是一个shasum或其他一些标识符,可以让我这样做 比较哈希与彼此。我希望像最后一个测试一样,如果哈希的内容匹配,它将返回true。
我可以在to_s
之前对哈希进行排序,但这对我来说似乎很狡猾。一世
我是一个人,害怕我在那里忽略了一些事情(一个sort
返回一个数组,不再是一个哈希值)。在那儿
我忽略了一些简单的东西?或者这根本不可能?
FWIW,我们在下面的场景中需要这个:
Analysis.find_by_config({scopes: [1,2], year: 2014}).datasets
Analysis.find_by_config({account_id: 1337}).datasets
class Analysis < ActiveRecord::Base
def self.find_by_config(config)
self.find_by(config_digest: shasum_of(config))
end
def self.shasum_of(config)
#WAT?
end
def before_saving
self.config_digest = Analysis.shasum_of(config)
end
end
请注意,此处,Analysis 不具有列“范围”或“年”或 “帐户ID”。这些是任意配置,我们只需要查看 数据集。
答案 0 :(得分:4)
我不推荐使用hash
方法,因为它不可靠。您可以通过在IRB中执行{one: 1}.hash
,在Rails控制台中执行相同的命令,然后在另一台机器上的IRB和/或Rails控制台中快速确认这一点。输出会有所不同。
坚持Digest::SHA2.hexdigest(string)
会更明智。
您必须对哈希进行排序并将其字符串化。这就是我要做的事情:
hash.sort.to_s
如果您不想要数组,无论出于何种原因,请将其转回哈希值。
Hash[hash.sort].to_s #=> will return hash
而且,无论出于何种原因,如果您不想将哈希值转换为数组然后返回哈希值,请执行以下操作以获取哈希值到哈希值:
def prepare_for_sum( hash )
hash.keys.sort.each_with_object({}) do |key, return_hash|
return_hash[key] = hash[key]
end.to_s
end
在上述方法中使用一些修改,您也可以对值进行排序;它可以在Array或Hash值的情况下提供帮助。
答案 1 :(得分:0)
事实证明,Ruby有一个针对这种情况的方法:Hash.hash
。
in_2014.hash == also_in_2014.hash