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 do an intersection using &. For example:
2.7.2 :001 > h = {"video"=>"MP4", "audio"=>"MP3", "sharing"=>"NONE", "mix"=>"NONE"}
=> {"video"=>"MP4", "audio"=>"MP3", "sharing"=>"NONE", "mix"=>"NONE"}
2.7.2 :002 > a = ["video", "audio", "txt"]
=> ["video", "audio", "txt"]
2.7.2 :003 > h.keys & a
=> ["video", "audio"]
2.7.2 :004 >
The explanation is: you got array of keys from hash(h.keys) and them get the intersection between array of keys and the array using &
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) }
You can also use intersection
with keys
(this approach kind of steps on other answers with &
operator here):
a.intersection(h.keys)
and you're going to get the following result with any of the solutions above:
=> ["video", "audio"]