Como pesquiso em uma matriz de hashes por valores de hash em ruby?

234

Eu tenho uma variedade 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 

Como posso pesquisar nessa matriz e retornar uma matriz de hashes para a qual um bloco retorna verdadeiro?

Por exemplo:

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

Obrigado.

doctororange
fonte

Respostas:

419

Você está procurando Enumerable # select (também chamado find_all):

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

De acordo com a documentação, "retorna uma matriz contendo todos os elementos [do enumerável, nesse caso @fathers] para os quais o bloco não é falso".

Jordan Running
fonte
22
Oh! Você foi o primeiro! Excluindo minha resposta e +1.
Milan Novota
20
Como nota, se você quiser encontrar apenas um (o primeiro), poderá usar @fathers.find {|father| father["age"] > 35 }.
Leigh McCulloch
1
É possível retornar o índice de onde isso foi encontrado na matriz original de hashes?
22816 Ian Warner
1
@IanWarner Sim. Eu sugiro olhar os documentos para o módulo Enumerable. Se você ainda não conseguir descobrir, poste uma nova pergunta.
Jordan Running
Acabei de fazer este índice = ARRAY.index {| h h [: code] == ARRAY ["code"]}
Ian Warner
198

isso retornará a primeira partida

@fathers.detect {|f| f["age"] > 35 }
Naveed
fonte
6
Eu prefiro isso #select- mas tudo vale para o seu caso de uso. #detectretornará nilse nenhuma correspondência for encontrada, enquanto #select, na resposta de @ Jordan, retornará [].
TJ Biddle
13
Você também pode usar findem vez de detectum código mais legível
Alter Lagos
8
findno entanto, pode ficar confuso nos trilhos.
user12341234
5
selecte detectnão são iguais, selectatravessarão toda a matriz, enquanto detectparará assim que a primeira correspondência for encontrada. Se você está procurando uma partida @fathers.select {|f| f["age"] > 35 }.firstcontra @fathers.detect {|f| f["age"] > 35 } desempenho e legibilidade, meu voto é paradetect
Naveed
35

se sua matriz parecer

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

E você deseja saber se algum valor já está presente em sua matriz. Use o método Find

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

Isso retornará objeto se Hitesh estiver presente no nome, caso contrário, retornará nulo

Hitesh Ranaut
fonte
Se o nome fosse minúsculo "hitesh", ele não retornaria o hash. Como podemos explicar também o uso de letras maiúsculas e minúsculas nesses casos?
Arjun
2
você pode usar algo parecido. array.find {| x | x [: name] .downcase == "Hitesh" .downcase}
Hitesh Ranaut