echan00
echan00

Reputation: 2807

Compare Hash Arrays in Ruby

I'm trying to compare and find the difference between two nested hashes with multiple hash arrays within arrays.

What is the best way to go about this comparison? It appears there are no libraries or functions that can help with this..

For example, I want the below two examples of hash a and hash b to be considered equal.

pry(main)> a
#⇒ {"197315"=>{:qty=>1,
#              :modifiers=>[{"197323-197319"=>{:qty=>1}},
#                           {"197322-197321"=>{:qty=>1}}]}}

pry(main)> b
#⇒ {"197315"=>{:qty=>1,
#              :modifiers=>[{"197322-197321"=>{:qty=>1}},
#                           {"197323-197319"=>{:qty=>1}}]}}

pry(main)> a == b
#⇒ false

pry(main)> a
#⇒ {"197315"=>{:qty=>1,
#              :modifiers=>[{"197322-197321"=>{
#                :qty=>1,
#                :modifiers=>['2222'=>'33333', '4444'=>'55555']}}, 
#                           {"197323-197319"=>{:qty=>1}}]}}

pry(main)> b
#⇒ {"197315"=>{:qty=>1,
#              :modifiers=>[{"197322-197321"=>{
#                :qty=>1,
#                :modifiers=>['4444'=>'55555', '2222'=>'33333']}},
#                            {"197323-197319"=>{:qty=>1}}]}}

pry(main)> a == b
#⇒ false

Upvotes: 1

Views: 56

Answers (1)

Cary Swoveland
Cary Swoveland

Reputation: 110675

This recursive solution should work with any number of levels of nested arrays and hashes.

Code

require 'set'

def arr_to_set(o)
  case o
  when Hash
    o.each_with_object({}) { |(k,v),g| g[k] = arr_to_set(v) }
  when Array
    o.map { |e| arr_to_set(e) }.to_set
  else
    o
  end
end

Examples

Example 1

a = {"197315"=>{:qty=>1, :modifiers=>[
                           {"197323-197319"=>{:qty=>1}},
                           {"197322-197321"=>{:qty=>1}}
                         ]
               }
    }

b = {"197315"=>{:qty=>1, :modifiers=>[
                           {"197322-197321"=>{:qty=>1}},
                           {"197323-197319"=>{:qty=>1}}
                         ]
               }
    }

arr_to_set(a) == arr_to_set(b)
  #=> true

Example 2

c = {"197315"=>{:qty=>1,
                :modifiers=>[
                  {"197322-197321"=>{ :qty=>1,
                                      :modifiers=>['2222'=>'33333', '4444'=>'55555']
                                    }
                  },
                  {"197323-197319"=>{:qty=>1}
                  }
                ]
              }
    }

d = {"197315"=>{:qty=>1,
                :modifiers=>[
                  {"197322-197321"=>{:qty=>1,
                                     :modifiers=>['4444'=>'55555', '2222'=>'33333']
                                    }
                  },
                  {"197323-197319"=>{:qty=>1}
                  }
                ]
               }
    }

arr_to_set(c) == arr_to_set(d)
  #=> true

Upvotes: 2

Related Questions