在 Ruby 中比较两个哈希数组,除了一个键。

3

我有两个哈希数组,像这样:

hashArray1 = [{"id"=>"1","data"=>"data1"},{"id"=>"2","data"=>"data2"}]
hashArray2 = [{"id"=>"3","data"=>"data1"},{"id"=>"4","data"=>"data2"}]

我希望比较它们,并在没有“id”键的情况下返回true。我尝试过类似这样的东西:
hashArray1.each do |h1|
  hashArray2.each do |h2|
    if h1.select{|h| h!= "id"} == h2.select{|b| b!= "id"}
      break
    else
      return false
    end
  end
end

但这似乎是不正确的。有没有更好的解决方案?我使用的是纯Ruby 1.9.3,没有使用Rails框架。

1
你的变量名hash1hash2是具有误导性的。它们不是哈希。 - sawa
@sawa 点已经记录,希望现在没问题了。不过问题已经得到回答了。 - Infant Dev
3个回答

2
我会简单地执行以下操作:
hash1.zip(hash2).all? do |h1,h2|
  return false unless h1.keys == h1.keys
  h1.keys.each do |key|
      return false if h1[key] != h2[key] unless key == 'id'
  end
end

2
如果 hash1.length != hash2.length,那么它们肯定不相同,你可以立即退出。如果它们长度相同,你可以这样做:
except_id = ->(h) { h.reject { |k, v| k == 'id' } }
same = hash1.zip(hash2).find { |h1, h2| except_id[h1] != except_id[h2] }.nil?

如果sametrue,则它们相同(忽略'id'),否则它们不同。使用Hash#reject是一种纯Ruby的方法,可以在不特定键的情况下非破坏性地查看哈希表。您也可以使用:

except_id = lambda { |h| h = h.dup; h.delete('id'); h }

如果“复制并删除”对您来说比过滤更有意义。如果您不喜欢find,那么all?可能会更容易理解:
same = hash1.zip(hash2).all? { |h1, h2| except_id[h1] == except_id[h2] }

甚至可以:
same_without_id = lambda { |h1, h2| except_id[h1] == except_id[h2] }
same == hash1.zip(hash2).all?(&same_without_id)

我也喜欢你的回答,但是由于@hirolau先回答了几乎相同的内容,所以接受他的回答,但是给你点赞。谢谢.. :) - Infant Dev

0
问题并不一定清晰,但我认为哈希的顺序被考虑在内。
hash1.map{|h| h.reject{|k, _| k == "id"}} ==
hash2.map{|h| h.reject{|k, _| k == "id"}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接