¿Cómo busco dentro de una matriz de valores hash por valores hash en ruby?

234

Tengo una variedad de hashes, @fathers.

a_father = { "father" => "Bob", "age" =>  40 }
@fathers << a_father
a_father = { "father" => "David", "age" =>  32 }
@fathers << a_father
a_father = { "father" => "Batman", "age" =>  50 }
@fathers << a_father 

¿Cómo puedo buscar en esta matriz y devolver una matriz de hashes para los que un bloque devuelve verdadero?

Por ejemplo:

@fathers.some_method("age" > 35) #=> array containing the hashes of bob and batman

Gracias.

doctor naranja
fuente

Respuestas:

419

Estás buscando Enumerable # select (también llamado find_all):

@fathers.select {|father| father["age"] > 35 }
# => [ { "age" => 40, "father" => "Bob" },
#      { "age" => 50, "father" => "Batman" } ]

Según la documentación, "devuelve una matriz que contiene todos los elementos de [el enumerable, en este caso @fathers] para el que el bloque no es falso".

Jordan Running
fuente
22
Oh! ¡Fuiste el primero! Eliminando mi respuesta y +1.
Milan Novota
20
Como nota, si solo desea encontrar uno solo (el primero) puede usarlo @fathers.find {|father| father["age"] > 35 }en su lugar.
Leigh McCulloch
1
¿Es posible devolver el índice de dónde se encontró esto en la matriz original de hashes?
Ian Warner
1
@IanWarner Sí. Sugiero mirar los documentos para el módulo Enumerable. Si aún no puede resolverlo, publique una nueva pregunta.
Jordan Running
Acabo de hacer este índice = ARRAY.index {| h | h [: code] == ARRAY ["code"]}
Ian Warner
198

esto devolverá el primer partido

@fathers.detect {|f| f["age"] > 35 }
Naveed
fuente
66
Prefiero esto antes #select, pero todo vale para su caso de uso. #detectregresará nilsi no se encuentra una coincidencia, mientras que #select, en la respuesta de @ Jordan, regresará [].
TJ Biddle
13
También puede usar en findlugar de detectun código más legible
Alter Lagos el
8
findSin embargo, puede ser confuso en los rieles.
user12341234
55
selecty detectno son iguales, selectatravesarán toda la matriz, mientras que detectse detendrán tan pronto como se encuentre la primera coincidencia. Si estás buscando UN partido @fathers.select {|f| f["age"] > 35 }.firstcontra @fathers.detect {|f| f["age"] > 35 } rendimiento y legibilidad, mi voto es paradetect
Naveed
35

si su matriz se ve así

array = [
 {:name => "Hitesh" , :age => 27 , :place => "xyz"} ,
 {:name => "John" , :age => 26 , :place => "xtz"} ,
 {:name => "Anil" , :age => 26 , :place => "xsz"} 
]

Y desea saber si algún valor ya está presente en su matriz. Utilice el método de búsqueda

array.find {|x| x[:name] == "Hitesh"}

Esto devolverá el objeto si Hitesh está presente en el nombre, de lo contrario, devuelve nil

Hitesh Ranaut
fuente
Si el nombre era minúscula "hitesh", no devolverá el hash. ¿Cómo podemos explicar también el uso de mayúsculas y minúsculas en tales casos?
arjun
2
puedes usar algo como array.find {| x | x [: name] .downcase == "Hitesh" .downcase}
Hitesh Ranaut el