如何比较关于元素顺序的两个多维哈希

我陷入了这样的问题。我尝试在rspec测试中比较2种哈希值:

describe 'sort tests' do
  let(:actual) do
    {
      1 => { users: { 1 => { id: 1,accounts: [1],profit: 10,revenue: 1,loss: 9 },2 => { id: 2,accounts: [2,3,6],profit: -24,revenue: 6,loss: -30 } },total_profit: -14,total_revenue: 7,total_loss: -21 },2 => { users: { 3 => { id: 3,accounts: [4,5],profit: 27,revenue: 9,loss: 18 } },total_profit: 27,total_revenue: 9,total_loss: 18 }
    }
  end
  let(:expected) do
    {
      1 => { users: { 2 => { id: 2,loss: -30 },1 => { id: 1,loss: 9 } },total_loss: 18 }
    }
  end

  it 'sort' do
    def mysort(data)
      data.each do |_,partner|
        partner[:users].sort_by { |_k,user| user[:loss] }.to_h
        partner
      end
      data.sort_by { |_,partner| partner[:total_loss] }.to_h
    end
    expect(mysort(actual)).to eql expected
    # expect(Digest::MD5.hexdigest(Marshal::dump(mysort(actual)))).to eql Digest::MD5.hexdigest(Marshal::dump(expected))
  end
end

测试通过了。但是,如果我取消对md5检查的注释,它将引发一个哈希不同的错误:

expected: "155d27d209f286fb1fc9ebeb0dcd6d3d"
     got: "255df98d4fc8166d0d8ffc7227ffd351"

因此,eql实际上不能正确比较散列,并且mysort函数中存在错误:

def mysort(data)
  data.each do |_,partner|
    partner[:users] = partner[:users].sort_by { |_k,user| user[:loss] }.to_h
    partner
  end
  data.sort_by { |_,partner| partner[:total_loss] }.to_h
end

现在排序还可以,但是仅比较md5校验和有助于了解哈希是否相等:(

如何在没有这种技巧的情况下比较哈希?

zyw52718 回答:如何比较关于元素顺序的两个多维哈希

我会用这样的东西:

compare = proc do |a,b|
  next a == b unless a.is_a?(Hash) && b.is_a?(Hash)
  next false  unless a.size == b.size

  a.keys.zip(b.keys).all?(compare) && a.values.zip(b.values).all?(compare)
end

在上述情况下,您无法将proc换成lambda。原因是proc隐式地执行数组分解而lambda则不这样做。 (您可以使用compare.([a,b])而不会破坏它,而使用lambda则无法做到。)

我个人是警卫条款的拥护者,主要是因为我发现它们比一个大表达更清晰。

此解决方案会同时检查顺序和值的顺序。

compare.({{a: 1,b: 2} => 1},{{b: 2,a: 1} => 1}) #=> false
compare.({a: {b: 2,c: 3}},{a: {c: 3,b: 2}})     #=> false
compare.({a: {b: 2,{a: {b: 2,c: 3}})     #=> true

ps。如果您使用的是2.5.0以下的Ruby版本,则必须改用.all?(&compare)(请注意&)。

本文链接:https://www.f2er.com/3080199.html

大家都在问