2010-09-25 16 views
153

Dado que tengo los clientes siguientes hash, ¿hay una forma rápida de ruby ​​(sin tener que escribir un script de varias líneas) para obtener la clave dada Quiero coincidir con el ¿Identificación del cliente? P.ej. Cómo obtener la clave para client_id == "2180"?Cómo encontrar una clave hash que contenga un valor coincidente

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

Respuesta

144

Usted podría utilizar Enumerable#select:

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

Tenga en cuenta que el resultado será una matriz de todos los valores coincidentes, en los que cada uno es un conjunto de la clave y valor.

+0

¡Esto también funciona! – Coderama

+18

@Coderama La diferencia entre 'encontrar' y' seleccionar' es que 'find' devuelve la primera coincidencia y' select' (que tiene el alias de 'findAll') devuelve todas las coincidencias. –

+0

Veo, por lo que esta sería la opción más segura para los casos donde hay más de una coincidencia. – Coderama

9

probar esto:

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

Esto funcionó muy bien – Coderama

+4

Esto lanzará una excepción si el resultado devuelve nil, porque no puede llamar a .first en nil. – Schrockwell

+1

Si usa Rails, puede usar '.try (: first)' en lugar de '.first' para evitar excepciones (si espera que sea posible que falte el valor). –

323

Ruby 1.9 y creciendo, y

hash.key(value) => key 

Rubí 1,8:

Usted podría utilizar hash.index

hsh.index(value) => key

Devuelve la clave para un valor determinado. Si no se encuentra , devuelve nil.

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

Así que para obtener "orange", es posible que utilices:

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

Obtengo nulo cuando ejecuto esto ... – Coderama

+0

@Coderama No lo hago: http://codepad.org/2JpX9ei5 – Aillyn

+2

Esto se volvería un tanto desordenado si los hash tuvieran varias claves, porque tendrías que dar el hash entero para 'indexar '. –

46

Puede invertir el hash. clients.invert["client_id"=>"2180"] vuelve "orange"

+3

¡Esto también parece una manera inteligente (porque es corta) de hacerlo! – Coderama

+0

esto es lo que necesito para matrices de formularios (para cuadros de selección) que crean un hash hacia atrás –

21

usted podría utilizar hashname.key (nombreDelValor)

O, una inversión puede estar en orden. new_hash = hashname.invert le dará un new_hash que le permite hacer las cosas más tradicionalmente.

+3

Esta es la forma correcta de hacerlo en versiones recientes (1.9+) de Ruby. –

+0

'# invert' es una muy mala idea en este caso, ya que esencialmente estás asignando memoria para tirar objetos hash solo por el bien de encontrar una clave. Dependiendo del tamaño del hash, tiene un serio impacto en el rendimiento –

3

A partir de los documentos:

  • (? Objeto) detectar (ifnone = nil) {| obj | ...}
  • (¿Objeto?) Encuentra (ifnone = nil) {| obj | ...}
  • (Objeto) detectar (ifnone = nil)
  • (Objeto) Buscar (ifnone = nil)

Pases cada entrada de enumeración para bloquear. Devuelve el primero para el cual el bloque no es falso. Si no coincide ningún objeto, llama a ifnone y devuelve su resultado cuando se especifica, o devuelve nil en caso contrario.

Si no se proporciona ningún bloque, se devuelve un enumerador.

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

Esto funcionó para mí:

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

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

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

0

La mejor manera de encontrar la clave para un valor particular es el uso de método clave que está disponible para un hash. ...

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

Espero que resuelva su problema ...

1

Otro enfoque me gustaría tratar es mediante el uso de #map

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

Esto devolverá todas las ocurrencias de valor dado. El guión bajo significa que no necesitamos que el valor de la clave se transmita para que no se asigne a una variable. La matriz contendrá nils si los valores no coinciden, por eso pongo #compact al final.

0

Aquí está una manera fácil de hacer encontrar las llaves de un valor dado:

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

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

... y para encontrar el valor de una determinada clave:

p clients.assoc("orange") 

que le dará la par clave-valor.

Cuestiones relacionadas