2015-04-12 45 views
2

我正在编写一个程序,它将扫描一个目录,获取文件中行的校验和,并将其与某个数据库进行比较,返回匹配的条目。Ruby - 从修改后的值重建哈希

我的数据库是一个包含文件名的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从数据库(由于这样的事实,红宝石不保留密钥的顺序)

由于sort_by将返回一个阵列,所述第一元件将是FILE_NAME,和第二元件将是行号散列,校验和

+1

您可以为dir_hash和database_hash添加一个示例输入,并且您希望重构的哈希值和修改后的值看起来像他们吗? – Sid

+0

那么你需要两个哈希的交集,对吧?键和值? – jazzytomato

+0

@Sid database_hash和dir_hash看起来像我在我的问题中的散列。只有真实的信息。从本质上讲,JSON文件(数据库)看起来像问题中的散列,当我扫描目录时,我创建了一个看起来相同的散列(即'filename => {:1 =>:checkusm,:2 =>:checksum ,:3 =>:checksum}}'唯一的区别是值(i。e文件名和校验和) – user2840647

回答

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

+0

嗯,出于某种原因,我得到的结果像'filename => {“1”=> nil,“2”=> nil,“3”=> nil}}' – user2840647

+0

虽然将其更改为'new_hash [ HASHES] [file] .select {| key | new_hash [:HASHES] [file] [key] == database_hash [:HASHES] [file] [key]}'似乎可以工作 – user2840647

+0

其实就是创建一个new_hash的'{“HASHES”=> {“file1”= > {“1”=>“1”,“2”=>“3”},“file2”=> {“1”=>“2”,“2”=>“4”}}}'看到我错过了你只需要交叉键值对,所以在这种情况下,就像你说的那样使用'select'! – Sid

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"}}} 
+0

是的,这就是最终的哈希应该是什么样子! – user2840647

+0

虽然,我希望找到一个不依赖于图书馆的解决方案。 – user2840647

+0

是的,图书馆是最糟糕的......我添加了一个香草红宝石实现。 – user12341234