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
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
To find the hashes with a certain key you can do.
def find_key_in list_of_hashes, key
list_of_hashes.select { |one_hash| one_hash.detect { |k,v| k == key }}
end
Call it like this:
irb(main):016:0> find_key_in [{a: 3, b: 2}, {b: 3, x: 4} ], :x
=> [{:b=>3, :x=>4}]
Printing the names of the hashes is tricker. See this question.
something like this?
arr = { 'a' => a, 'b' => b, 'c' =>c}
#=> {"a"=>{"A"=>1, "B"=>1, "C"=>1}, "b"=>{"A"=>1, "B"=>1, "D"=>1, "E"=>1}, "c"=>{"D"=>1, "E"=>1, "F"=>1}}
def my_method(letter, arr)
arr.map { |el| "#{letter} is in #{el[0]}" if !el[1]["#{letter}"].nil? }.compact
end
example:
my_method("A", arr)
#=> ["A is in a", "A is in b"]