我正在编写一个程序,它将扫描目录,获取文件中行的校验和,并将其与某个数据库进行比较,返回匹配的条目。
我的数据库是一个json文件,包含文件名和行的校验和,它看起来像这样:
"HASHES": {
"file_name": {
"1": "checksum",
"2": "checksum"
},
"file_name": {
"1": "checksum",
"2": "checksum
},
etc..
}
然后我扫描目录并构造一个类似的哈希(即file_name,行号,校验和的哈希)。这段代码有效。
我遇到的问题是从结果重建类似的哈希
这是我的代码:
def compare(dir_hash, database_hash)
temp_hash = database_hash.dup
# retrieve the checksums from the dir_hash.
dir_values = dir_hash["HASHES"].sort_by(&:first).map { |x| x.last.values }
# retrieve the checksums from database_hash
db_values = database_hash["HASHES"].sort_by(&:first).map { |x| x.last.values }
# perform a set intersection to get the common values
unique_values = dir_values.zip(db_values).map { |x| x.reduce(:&) }
# code to reconstruct hash, based on new values
new_hash = temp_hash["HASHES"]
end
我似乎无法弄清楚如何使用修改后的值重建哈希。
帮助表示赞赏。
注意
sort_by(&:first)
的目的是确保当我们执行集合交集时,我们在相同的值上执行它,换句话说,我从文件x
获取集合的交集数据库中的目录和相同的文件x
(由于Ruby不保留键的顺序)
由于sort_by
将返回一个数组,第一个元素将是file_name,第二个元素将是行号的哈希值,校验和
答案 0 :(得分:1)
另一种方法可以做到这一点:
intersect_ary = database_hash["HASHES"].keys & dir_hash["HASHES"].keys
new_hash = dir_hash
intersect_ary.each do |file|
new_hash["HASHES"][file].select! {|key| new_hash["HASHES"][file][key] == database_hash["HASHES"][file][key]}
end
(假设你必须创建一个新的哈希而不是仅仅改变dir_hash
)
答案 1 :(得分:0)
我不太确定你的问题应该是什么样的正确输出,但是我正在开发一个旨在让它更容易使用嵌套集合的库,所以我想我会给它一个刺。这是你的想法吗?
注意:此解决方案依赖于https://github.com/dgopstein/deep_enumerable
中的代码require './deep_enumerable/lib/deep_enumerable.rb'
dir_hash = {
"HASHES": {
"file1": {
"1": "1",
"2": "2"
},
"file2": {
"1": "3",
"2": "4"
}
}
}
database_hash = {
"HASHES": {
"file1": {
"1": "1",
"2": "3"
},
"file2": {
"1": "2",
"2": "4"
}
}
}
p dir_hash.deep_intersect(database_hash)
=> {:HASHES=>{:file1=>{:"1"=>"1"}, :file2=>{:"2"=>"4"}}}
或者没有库(在这个例子之外未经测试):
def deep_intersect(this, other, &block)
empty = this.select{false}
(this.keys + other.keys).each do |key|
s_val = (this[key] rescue nil)
o_val = (other[key] rescue nil)
comparator = block || :==.to_proc
if s_val.is_a?(Hash) && o_val.is_a?(Hash)
int = deep_intersect(s_val, o_val, &block)
if !int.empty?
empty[key] = int
end
elsif comparator.call(s_val, o_val)
empty[key] = s_val
end
end
empty
end
p deep_intersect(dir_hash, database_hash)
=> {:HASHES=>{:file1=>{:"1"=>"1"}, :file2=>{:"2"=>"4"}}}