Reputation: 7512
I'm looking for a better way to do
if hash.key? :a &&
hash.key? :b &&
hash.key? :c &&
hash.key? :d
preferably something like
hash.includes_keys? [ :a, :b, :c, :d ]
I came up with
hash.keys & [:a, :b, :c, :d] == [:a, :b, :c, :d]
but I dont like having to add the array twice though
Upvotes: 63
Views: 39438
Reputation: 323
Here is my solution:
class Hash
# doesn't check recursively
def same_keys?(compare)
return unless compare.class == Hash
self.size == compare.size && self.keys.all? { |s| compare.key?(s) }
end
end
a = c = { a: nil, b: "whatever1", c: 1.14, d: false }
b = { a: "foo", b: "whatever2", c: 2.14, "d": false }
d = { a: "bar", b: "whatever3", c: 3.14, }
puts a.same_keys?(b) # => true
puts a.same_keys?(c) # => true
puts a.same_keys?(d) # => false
puts a.same_keys?(false).inspect # => nil
puts a.same_keys?("jack").inspect # => nil
puts a.same_keys?({}).inspect # => false
Upvotes: 1
Reputation: 2083
You can get a list of missing keys this way:
expected_keys = [:a, :b, :c, :d]
missing_keys = expected_keys - hash.keys
If you just want to see if there are any missing keys:
(expected_keys - hash.keys).empty?
Upvotes: 9
Reputation: 1250
I like this way to solve this:
subset = [:a, :b, :c, :d]
subset & hash.keys == subset
It is fast and clear.
Upvotes: 8
Reputation: 37517
Just in the spirit of TIMTOWTDI, here's another way. If you require 'set'
(in the std lib) then you can do this:
Set[:a,:b,:c,:d].subset? hash.keys.to_set
Upvotes: 15
Reputation: 41179
@Mori's way is best, but here's another way:
([:a, :b, :c, :d] - hash.keys).empty?
or
hash.slice(:a, :b, :c, :d).size == 4
Upvotes: 21