Как найти хэш-ключ, содержащий соответствующее значение

Учитывая, что у меня есть хеш ниже клиентов, есть ли быстрый рубиновый способ (без необходимости писать многострочный script), чтобы получить ключ, который я хочу сопоставить с client_id? Например. Как получить ключ для client_id == "2180"?

clients = {
  "yellow"=>{"client_id"=>"2178"}, 
  "orange"=>{"client_id"=>"2180"}, 
  "red"=>{"client_id"=>"2179"}, 
  "blue"=>{"client_id"=>"2181"}
}

Ответ 1

Вы можете использовать Enumerable # select:

clients.select{|key, hash| hash["client_id"] == "2180" }
#=> [["orange", {"client_id"=>"2180"}]]

Обратите внимание, что результатом будет массив всех совпадающих значений, каждый из которых является массивом ключа и значения.

Ответ 2

Ruby 1.9 и больше:

hash.key(value) => key

Ruby 1.8:

Вы можете использовать hash.index

hsh.index(value) => key

Возвращает ключ для заданного значения. Если не найден, возвращает nil.

h = { "a" => 100, "b" => 200 }
h.index(200) #=> "b"
h.index(999) #=> nil

Итак, чтобы получить "orange", вы можете просто использовать:

clients.key({"client_id" => "2180"})

Ответ 3

Вы можете инвертировать хэш. clients.invert["client_id"=>"2180"] возвращает "orange"

Ответ 4

Вы можете использовать hashname.key(valuename)

Или инверсия может быть в порядке. new_hash = hashname.invert предоставит вам new_hash, который позволит вам делать что-то более традиционно.

Ответ 5

В соответствии с ruby ​​doc http://www.ruby-doc.org/core-1.9.3/Hash.html#method-i-key ключ (значение) - это метод поиска ключа на основе значения.

ROLE = {"customer" => 1, "designer" => 2, "admin" => 100}
ROLE.key(2)

он вернет "конструктор".

Ответ 6

попробуйте следующее:

clients.find{|key,value| value["client_id"] == "2178"}.first

Ответ 7

Из документов:

  • (Object?) обнаруживает (ifnone = nil) {| obj |...}
  • (Object?) find (ifnone = nil) {| obj |...}
  • (Object) detect (ifnone = nil)
  • (Object) find (ifnone = nil)

Пропускает каждую запись в перечислении для блокировки. Возвращает первый, для которого блок не является ложным. Если объект не соответствует, вызывает ifnone и возвращает его результат, когда он указан, или возвращает иначе.

Если блок не указан, вместо него возвращается счетчик.

(1..10).detect  {|i| i % 5 == 0 and i % 7 == 0 }   #=> nil
(1..100).detect {|i| i % 5 == 0 and i % 7 == 0 }   #=> 35

Это сработало для меня:

clients.detect{|client| client.last['client_id'] == '2180' } #=> ["orange", {"client_id"=>"2180"}] 

clients.detect{|client| client.last['client_id'] == '999999' } #=> nil 

См: http://rubydoc.info/stdlib/core/1.9.2/Enumerable#find-instance_method

Ответ 8

Другой подход, который я попробовал бы, это использовать #map

clients.map{ |key, _| key if clients[key] == {"client_id"=>"2180"} }.compact 
#=> ["orange"]

Это вернет все вхождения заданного значения. Подчеркивание означает, что нам не нужно использовать значение ключа, чтобы оно не было привязано к переменной. Массив будет содержать nils, если значения не совпадают - поэтому я положил #compact в конец.

Ответ 9

Лучший способ найти ключ для определенного значения - использовать ключевой метод, доступный для хеша....

gender = {"MALE" => 1, "FEMALE" => 2}
gender.key(1) #=> MALE

Я надеюсь, что он решает вашу проблему...

Ответ 10

Вот простой способ найти ключи заданного значения:

    clients = {
      "yellow"=>{"client_id"=>"2178"}, 
      "orange"=>{"client_id"=>"2180"}, 
      "red"=>{"client_id"=>"2179"}, 
      "blue"=>{"client_id"=>"2181"}
    }

    p clients.rassoc("client_id"=>"2180")

... и найти значение заданного ключа:

    p clients.assoc("orange") 

он даст вам пару ключ-значение.