我有两个这样的哈希数组:
hashArray1 = [{"id"=>"1","data"=>"data1"},{"id"=>"2","data"=>"data2"}]
hashArray2 = [{"id"=>"3","data"=>"data1"},{"id"=>"4","data"=>"data2"}]
我想比较它们两个并返回true如果其他所有匹配没有“id”键。
我试过这样的事情:
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框架。
我会这样做:
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
如果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?
如果same
是true
然后他们是相同的(而忽略'id'
s),否则他们是不同的。使用Hash#reject
是一种纯粹的Ruby方式,可以在没有特定键的情况下非破坏性地查看Hash。你也可以使用:
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)
问题不一定清楚,但我假设哈希的顺序被考虑在内。
hash1.map{|h| h.reject{|k, _| k == "id"}} ==
hash2.map{|h| h.reject{|k, _| k == "id"}}