T0ny lombardi
T0ny lombardi

Reputation: 1920

Ruby Compare 2 hashes

Is there a way to compare 2 hashes if the keys are not in the same order? for instance

hash1 = { "it"=> 10,"was"=>11,"the"=>14,"best"=>1,"of"=>12,"times"=>2,
          "worst"=>1,"age"=>2,"wisdom"=>1,"foolishness"=>1,"epoch"=>2,
          "belief"=>1,"incredulity"=>1,"season"=>2,"light"=>1,"darkness"=>1,
          "spring"=>1,"hope"=>1,"winter"=>1,"despair"=>1,"we"=>4,"had"=>2,
          "everything"=>1,"before"=>2,"us"=>2,"nothing"=>1,"were"=>2,"all"=>2,
          "going"=>2,"direct"=>2,"to"=>1,"heaven"=>1,"other"=>1,
          "way"=>1,"in"=>2,"short"=>1,"period"=>2,"so"=>1,"far"=>1,"like"=>1,
          "present"=>1,"that"=>1,"some"=>1,"its"=>2,"noisiest"=>1,
          "authorities"=>1,"insisted"=>1,"on"=>1,"being"=>1,
          "received"=>1,"for"=>2,"good"=>1,"or"=>1,"evil"=>1,"superlative"=>1,
          "degree"=>1,"comparison"=>1,"only"=>1 }


hash2 = {"superlative"=>1, "it"=>10, "going"=>2, "spring"=>1, "age"=>2, 
         "despair"=>1, "received"=>1, "good"=>1, "some"=>1, "worst"=>1, "was"=>11,
         "only"=>1,"us"=>2, "evil"=>1, "belief"=>1, "for"=>2, "darkness"=>1,
         "comparison"=>1, "short"=>1, "in"=>2, "present"=>1, "direct"=>2, "were"=>2,
         "way"=>1, "degree"=>1, "or"=>1, "of"=>12, "epoch"=>2, "incredulity"=>1,
         "period"=>2, "heaven"=>1, "other"=>1, "being"=>1, "its"=>2, "so"=>1,
         "authorities"=>1, "times"=>2, "we"=>4, "noisiest"=>1, "light"=>1, "hope"=>1,
         "foolishness"=>1, "everything"=>1, "far"=>1, "wisdom"=>1, "season"=>2, "like"=>1,
         "before"=>2, "had"=>2, "the"=>14, "nothing"=>1, "winter"=>1, "best"=>1,
         "that"=>1, "all"=>2, "insisted"=>1, "to"=>1, "on"=>1}

Each hash has the same keys. How would I go about comparing them and making sure that each key value is correct. All the questions and answers I've seen show hashes with the keys in the same order. Does it matter?

I've tried to use:

hash1_1 = hash1.select{|k,_| hash2.has_key? k}

which spit out:

{ "it"=>10, "was"=>11, "the"=>14, "best"=>1, "of"=>12, "times"=>2, 
     "worst"=>1, "age"=>2, "wisdom"=>1, "foolishness"=>1, "epoch"=>2, 
     "belief"=>1, "incredulity"=>1, "season"=>2, "light"=>1, 
     "darkness"=>1, "spring"=>1, "hope"=>1, "winter"=>1, "despair"=>1, 
     "we"=>4, "had"=>2, "everything"=>1, "before"=>2, "us"=>2, "nothing"=>1, 
     "were"=>2, "all"=>2, "going"=>2, "direct"=>2, "to"=>1, "heaven"=>1, 
     "other"=>1, "way"=>1, "in"=>2, "short"=>1, "period"=>2, "so"=>1, "far"=>1, 
     "like"=>1, "present"=>1, "that"=>1, "some"=>1, "its"=>2, "noisiest"=>1, 
     "authorities"=>1, "insisted"=>1, "on"=>1, "being"=>1, "received"=>1, 
     "for"=>2, "good"=>1, "or"=>1, "evil"=>1, "superlative"=>1, "degree"=>1, 
     "comparison"=>1, "only"=>1}

Please help me in explaining what I need to do. Thank you.

Upvotes: 0

Views: 4760

Answers (3)

Alex_L
Alex_L

Reputation: 66

As I understand correctly, your main goal was to answer, if there is any difference between two hashes. So, the result of comparison should be true in case of exact match (both keys and corresponding values of two hashes), or false if not. As mentioned here, since Ruby 2.3. you could use:

{ a: 1 } <= { a: 1 } = true
{ a: 1 } <= { a: 2 } = false
{ a: 2 } <= { a: 1 } = false
{ a: 2 } <= { a: 2 } = true
{ a: 1 } >= { a: 1 } = true
{ a: 1 } >= { a: 2 } = false
{ a: 2 } >= { a: 1 } = false
{ a: 2 } >= { a: 2 } = true
{ a: 1 } <  { a: 1 } = false
{ a: 1 } <  { a: 2 } = false
{ a: 2 } <  { a: 1 } = false
{ a: 2 } <  { a: 2 } = false
{ a: 1 } >  { a: 1 } = false
{ a: 1 } >  { a: 2 } = false
{ a: 2 } >  { a: 1 } = false
{ a: 2 } >  { a: 2 } = false
{ a: 1 } == { a: 1 } = true
{ a: 1 } == { a: 2 } = false

and

{ a: 1, b: 2 } > { a: 1 } = true
{ a: 1, b: 2 } == { a: 1 } = false
{ a: 1, b: 2 } >= { a: 1 } = true
{ a: 1, b: 2 } > { a: 1, b: 5 } = false

Upvotes: 0

Jeff Price
Jeff Price

Reputation: 3229

You are misinterpreting your results. Your code, works fine. Your algorithm is wrong though.

I'll take your hash1 and hash2 and create a difference using reject to get rid of everything that matches between them:

hash1["it"] = 9
hash1["Tony"] = "great"
hash2["Jeff"] = "awesome"
hash1.delete "was"

diff_in_hash1 = hash1.reject{|k,v| hash2[k] == v}
# => {"it"=>9, "Tony"=>"great"}

diff_in_hash2 = hash2.reject{|k,v| hash1[k] == v}
# => {"it"=>10, "was"=>11, "Jeff"=>"awesome"}

What you do with them now, is up to you. If you get empty hashes as a result, everything is the same.

There is also a gem called 'hashdiff' that could be of use.

Upvotes: 3

infused
infused

Reputation: 24337

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

Upvotes: 5

Related Questions