Home > Software design >  Fetch hash keys that are present in array
Fetch hash keys that are present in array

Time:07-30

I have a use case where I want to fetch keys from a hash which are present in a separate array.

Example:

h = {"video"=>"MP4", "audio"=>"MP3", "sharing"=>"NONE", "mix"=>"NONE"}
a = ["video", "audio", "txt"]

Expected result:

["video", "audio"]

I am trying to use slice method on hash but it is not working for me:

h.slice(a)

Any help would be appreciated.

CodePudding user response:

The reason you attempt doesn't work is that hash keys can actually be any kind of object and Hash#slice will compare them by identity:

# its a hash with array keys - crazy stuff.
=> {[1, 2, 3]=>"a", [3, 4, 5]=>"b"}
irb(main):012:0> hash.slice([1,2,3])
=> {[1, 2, 3]=>"a"}
# [1,2,3] and [1,2] are not equal
irb(main):013:0> hash.slice([1,2])
=> {}
irb(main):014:0> hash.slice([3,4,5])
=> {[3, 4, 5]=>"b"}
irb(main):015:0> 

An array will never be equal to a string in Ruby.

If you want to convert an array into a list of arguments to pass to a method use the splat operator (*):

irb(main):022:0> h = {"video"=>"MP4","audio"=>"MP3", "sharing"=>"NONE", "mix"=>"NONE"}
=> {"video"=>"MP4", "audio"=>"MP3", "sharing"=>"NONE", "mix"=>"NONE"}
irb(main):023:0> a = ["video", "audio", "txt"]
=> ["video", "audio", "txt"]
irb(main):024:0> h.slice(*a)
=> {"video"=>"MP4", "audio"=>"MP3"}

CodePudding user response:

You can try filter with a proc (which checks for h key inclusion):

a.filter(&h.method(:key?))

which is essentially the same as using a block:

a.filter { |a_i| h.key?(a_i) }

and you get the following result:

=> ["video", "audio"]
  • Related