Comparing Ruby Hashes

How do I compare two hashes?

You can compare hashes directly for equality:

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


You can convert the hashes to arrays, then get their difference:

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}

Simplifying further:

Assigning difference via a ternary structure:

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

Doing it all in one operation and getting rid of the difference variable:

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

Ruby Compare 2 hashes

Two hashes with the same key/value pairs will be equal regardless of key order:

a = {:x => 1, :y => 2}
b = {:y => 2, :x => 1}

a == b
# => true

compare two hashes in ruby

# normalization
h1, h2 = [hash1, hash2].map do |h|
h.map do |k, v|
[k.to_s.downcase, v.to_s.to_i.to_s == v.to_s ? v.to_i : v]
end.to_h
end

Now we are ready to compare:

h1.reject { |k, v| h2[k].nil? || h2[k] == v }
#⇒ { "g" => "2.25000000" }

This might be printed, formatted etc as you want.

Compare two hashes no matter symbols or strings, rails

How about this?

require 'set'

def sorta_equal?(sym_hash, str_hash)
return false unless sym_hash.size == str_hash.size
sym_hash.to_a.to_set == str_hash.map { |pair|
pair.map { |o| o.is_a?(String) ? o.to_sym : o } }.to_set
end

sym_hash= {:id=>58, :locale=>:"en-US"}

sorta_equal?(sym_hash, {"id"=>58, "locale"=>"en-US"}) #=> true
sorta_equal?(sym_hash, {"locale"=>"en-US", "id"=>58 }) #=> true
sorta_equal?(sym_hash, {"id"=>58, "local"=>"en-US", "a"=>"b" }) #=> false
sorta_equal?(sym_hash, {"id"=>58, "lacole"=>"en-US"}) #=> false
sorta_equal?(sym_hash, {"id"=>58, [1,2,3]=>"en-US"}) #=> false
sorta_equal?({}, {}) #=> true

class A; end
a = A.new
sorta_equal?({:id=>a, :local=>:b}, {"id"=>a, "local"=>"b"}) #=> true

How to compare this two hashes in ruby

1. Symbolize keys

These hashes are not equal because the keys are not equal. If you want to compare the values, no matter whether the keys are strings or symbols you can just transform the keys using to_sym. (Note that this will not transform nested keys).

first_hash.transform_keys(&:to_sym) == second_hash.transform_keys(&:to_sym)

2. Compare as JSON (NOT RECOMMENDED)

I do not recommend this, but since it is technically possible, I included it here for fun and informational purposes.

Another way you can do this is to check whether the JSON representation is the same. It is probably slower, and requires the keys to be in the same order in each hash.

require 'json'
first_hash.to_json == second_hash.to_json

How to compare 2 hashes and findout how many nested hashes have changed

I think you can do hash1.to_a - hash2.to_a to obtain the differences



Related Topics



Leave a reply



Submit