我如何比较两个哈希?

den*_*icz 99 ruby hash

我试图使用以下代码比较两个Ruby Hashes:

#!/usr/bin/env ruby

require "yaml"
require "active_support"

file1 = YAML::load(File.open('./en_20110207.yml'))
file2 = YAML::load(File.open('./locales/en.yml'))

arr = []

file1.select { |k,v|
  file2.select { |k2, v2|
    arr << "#{v2}" if "#{v}" != "#{v2}"
  }
}

puts arr
Run Code Online (Sandbox Code Playgroud)

屏幕输出是file2的完整文件.我知道文件不同的事实,但脚本似乎没有拿起它.

the*_*Man 151

您可以直接比较哈希的相等性:

hash1 = {'a' => 1, 'b' => 2}
hash2 = {'a' => 1, 'b' => 2}
hash3 = {'a' => 1, 'b' => 2, 'c' => 3}

hash1 == hash2 # => true
hash1 == hash3 # => false

hash1.to_a == hash2.to_a # => true
hash1.to_a == hash3.to_a # => false
Run Code Online (Sandbox Code Playgroud)

你可以将哈希转换为数组,然后得到它们的区别:

hash3.to_a - hash1.to_a # => [["c", 3]]

if (hash3.size > hash1.size)
  difference = hash3.to_a - hash1.to_a
else
  difference = hash1.to_a - hash3.to_a
end
Hash[*difference.flatten] # => {"c"=>3}
Run Code Online (Sandbox Code Playgroud)

进一步简化:

通过三元结构分配差异:

  difference = (hash3.size > hash1.size) \
                ? hash3.to_a - hash1.to_a \
                : hash1.to_a - hash3.to_a
=> [["c", 3]]
  Hash[*difference.flatten] 
=> {"c"=>3}
Run Code Online (Sandbox Code Playgroud)

在一个操作中完成所有操作并删除difference变量:

  Hash[*(
  (hash3.size > hash1.size)    \
      ? hash3.to_a - hash1.to_a \
      : hash1.to_a - hash3.to_a
  ).flatten] 
=> {"c"=>3}
Run Code Online (Sandbox Code Playgroud)

  • 散列可以具有相同的大小,但包含不同的值.在这种情况下,`hash1.to_a - hash3.to_a`和`hash3.to_a - hash1.to_a`都可以通过`hash1.size == hash3.size`返回非空值.**编辑**之后的部分仅在哈希值不同时才有效. (5认同)
  • 反正有没有得到两者之间的差异? (3认同)
  • 很好,但应该在前方退出.A.size> B.size并不一定意味着A包括B.仍然需要采取对称差异的联合. (3认同)

小智 32

您可以尝试使用hashdiff gem,它允许深入比较散列中的散列和数组.

以下是一个例子:

a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
b = {a:{y:3}, b:{y:3, z:30}}

diff = HashDiff.diff(a, b)
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]
Run Code Online (Sandbox Code Playgroud)

  • 我有一些相当深的哈希导致测试失败.通过将`got_hash.should eql expected_hash`替换为`HashDiff.diff(got_hash,expected_hash).should eql []`我现在得到输出,显示我需要的确切内容.完善! (3认同)
  • 我对 HashDiff 的经验是,它对于小哈希非常有效,但 diff 速度似乎不能很好地扩展。值得对您的调用进行基准测试,如果您预计它可能会得到两个大的哈希值并确保差异时间在您的容忍范围内。 (2认同)

Gui*_*nal 15

如果你想得到两个哈希之间的区别,你可以这样做:

h1 = {:a => 20, :b => 10, :c => 44}
h2 = {:a => 2, :b => 10, :c => "44"}
result = {}
h1.each {|k, v| result[k] = h2[k] if h2[k] != v }
p result #=> {:a => 2, :c => "44"}
Run Code Online (Sandbox Code Playgroud)


Eva*_*van 11

Rails正在弃用diff方法.

快速单行:

hash1.to_s == hash2.to_s
Run Code Online (Sandbox Code Playgroud)

  • 当相等的哈希值具有不同的顺序时,它将失败:`{a:1,b:2} == {b:2,a:1}`=> true,`{a:1,b:2}. to_s == {b:2,a:1} .to_s` => false (16认同)
  • 这是一个特点!:D (2认同)

Erv*_*ouS 5

您可以使用简单的数组交集,这样您就可以知道每个哈希的区别。

    hash1 = { a: 1 , b: 2 }
    hash2 = { a: 2 , b: 2 }

    overlapping_elements = hash1.to_a & hash2.to_a

    exclusive_elements_from_hash1 = hash1.to_a - overlapping_elements
    exclusive_elements_from_hash2 = hash2.to_a - overlapping_elements
Run Code Online (Sandbox Code Playgroud)