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"]