Reputation: 494
I have a hash categories as following:
categories = {"horeca" => ["bar", "waiter", "kitchen"],
"retail" => ["eerste", "tweede"]}
I want to find they key if the value is included in the array of values.
Something like following
categories.key("bar")
which would return "horeca"
as of now I can only get "horeca" if I do
categories.key(["bar", "waiter", "kitchen"])
Upvotes: 4
Views: 12269
Reputation: 1968
Md. Farhan Memon's solution is generally the preferable solution but it has one downside: If there's no match in the collection, it returns the collection itself – which probably isn't a desirable result. You can fix this with a simple adjustment that combines both detect/find
and break
:
categories.detect { |key, values| break key if values.include?('bar') }
This breaks and returns the value if it finds it and otherwise returns nil
(which I assume to be the preferable behavior).
If your collection may also contain nil
values and/or non-arrays, you can improve it further:
categories.detect { |key, values| break key if Array(values).include?('bar') }
The only downside of this general approach is that it's not particularly intuitive to newcomers: You have to know a bit more than just basic Ruby to understand what's going on without running the code first.
Upvotes: 3
Reputation: 6121
Creating intermediate array and then calling first on it is all unnecessary, also if the hash is large and you want first matched value, following solution is better
categories.each{ |k,v| break k if v.include?('bar') }
#=> "horeca"
Upvotes: 3
Reputation: 681
As Máté mentioned, you can use find
if you want to find the first matching element. Use select
if you want all matching elements. To just get the keys you would do:
categories.select { |key, values| values.include?("bar") }.map(&:first)
See https://ruby-doc.org/core-2.2.3/Enumerable.html#method-i-select
Upvotes: 5
Reputation: 5977
Try Enumberable#find
:
categories.find { |key, values|
values.include?("bar")
}.first
Upvotes: 7