Search code examples
rubyhashunique

Finding duplicate keys across hashes?


To simplify things let's say I have the hashes below.

I would like to find the keys that are in multiple hashes and the name of the hashes. So ideally I would like to end up with

A is also in  a
A is also in  b
B is also in  a
B is also in  b
D is also in  b
D is also in  c
E is also in  b
E is also in  c

The only way I can think of is: putting all keys in an array, sort it, remove unique elements, search each hash that contain the remaing array elements.

It is somewhat complicated and hacky I guess.

Question

Is there an easier way to find duplicate keys across hashes?

!/usr/bin/ruby                                                                                          

require 'ap'

a = {}
b = {}
c = {}

a["A"] = 1
a["B"] = 1
a["C"] = 1

b["A"] = 1
b["B"] = 1
b["D"] = 1
b["E"] = 1

c["D"] = 1
c["E"] = 1
c["F"] = 1

Solution

  • You could build another hash to store each key and its hashes:

    keys = Hash.new { |hash, key| hash[key] = [] }
    a.each_key { |k| keys[k] << :a }
    b.each_key { |k| keys[k] << :b }
    c.each_key { |k| keys[k] << :c }
    

    More precisely, keys stores an array of symbols. It looks like this after running the above code:

    keys
    #=> {"A"=>[:a, :b],
    #    "B"=>[:a, :b],
    #    "C"=>[:a],
    #    "D"=>[:b, :c],
    #    "E"=>[:b, :c],
    #    "F"=>[:c]}
    

    To get your expected output:

    keys.each do |key, hashes|
      next if hashes.size < 2
      hashes.each { |hash| puts "#{key} is also in #{hash}" }
    end
    

    Prints:

    A is also in a
    A is also in b
    B is also in a
    B is also in b
    D is also in b
    D is also in c
    E is also in b
    E is also in c