Reputation: 11352
Given I have the below clients hash, is there a quick ruby way (without having to write a multi-line script) to obtain the key given I want to match the client_id? E.g. How to get the key for client_id == "2180"
?
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
Upvotes: 244
Views: 320074
Reputation: 3939
We write 2023: (so for all stumbling in here)
find
is what you are searching for.
But find
returns an array on match or NIL for no match. If we use the argument of find
(a proc that is called if no match), and use proc {[]}
, we get an empty array on a non-matching find, that fits better to a hash.
people = {
ralph: { name: "rafael", … },
eve: { name: "eveline", … }
…
}
people[:eve] => {name: "eveline",…}
people.find { |nick, person| person.name=="rafael" }[1] => { name: "rafael", … }
and
people[:tosca] => nil
people.find { |nick, person| person.name=="toska" }[1] => BANG ([] on nil)
but
people.find(proc {[]}) { |nick, person| person.name=="toska" }[1] => nil
So if you have an id-like attribute, you can do like that:
person=people[id]
person||=people.find({[]}) { |p| p.nick == id }[1]
person||=people.find({[]}) { |p| p.other_nick == id }[1]
raise error unless person
Upvotes: 0
Reputation: 23793
Ruby 1.9 and greater:
hash.key(value) => key
Ruby 1.8:
You could use hash.index
hsh.index(value) => key
Returns the key for a given value. If not found, returns
nil
.
h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil
So to get "orange"
, you could just use:
clients.key({"client_id" => "2180"})
Upvotes: 484
Reputation: 174
Heres an easy way to do find the keys of a given value:
clients = {
"yellow"=>{"client_id"=>"2178"},
"orange"=>{"client_id"=>"2180"},
"red"=>{"client_id"=>"2179"},
"blue"=>{"client_id"=>"2181"}
}
p clients.rassoc("client_id"=>"2180")
...and to find the value of a given key:
p clients.assoc("orange")
it will give you the key-value pair.
Upvotes: 1
Reputation: 816
Another approach I would try is by using #map
clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact
#=> ["orange"]
This will return all occurences of given value. The underscore means that we don't need key's value to be carried around so that way it's not being assigned to a variable. The array will contain nils if the values doesn't match - that's why I put #compact
at the end.
Upvotes: 2
Reputation: 4551
According to ruby doc http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-key key(value) is the method to find the key on the base of value.
ROLE = {"customer" => 1, "designer" => 2, "admin" => 100}
ROLE.key(2)
it will return the "designer".
Upvotes: 14
Reputation: 1570
The best way to find the key for a particular value is to use key method that is available for a hash....
gender = {"MALE" => 1, "FEMALE" => 2}
gender.key(1) #=> MALE
I hope it solves your problem...
Upvotes: 4
Reputation: 38418
From the docs:
Passes each entry in enum to block. Returns the first for which block is not false. If no object matches, calls ifnone and returns its result when it is specified, or returns nil otherwise.
If no block is given, an enumerator is returned instead.
(1..10).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 } #=> 35
This worked for me:
clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}]
clients.detect{|client| client.last['client_id'] == '999999' } #=> nil
See: http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method
Upvotes: 6
Reputation: 39695
You could use hashname.key(valuename)
Or, an inversion may be in order. new_hash = hashname.invert
will give you a new_hash
that lets you do things more traditionally.
Upvotes: 24
Reputation: 18333
You can invert the hash. clients.invert["client_id"=>"2180"]
returns "orange"
Upvotes: 51
Reputation: 1793
try this:
clients.find{|key,value| value["client_id"] == "2178"}.first
Upvotes: 20
Reputation: 94103
You could use Enumerable#select:
clients.select{|key, hash| hash["client_id"] == "2180" }
#=> [["orange", {"client_id"=>"2180"}]]
Note that the result will be an array of all the matching values, where each is an array of the key and value.
Upvotes: 197