Wie suche ich in einem Array von Hashes nach Hashwerten in Ruby?

234

Ich habe eine Reihe von 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 

Wie kann ich dieses Array durchsuchen und ein Array von Hashes zurückgeben, für die ein Block true zurückgibt?

Beispielsweise:

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

Vielen Dank.

Doktororange
quelle

Antworten:

419

Sie suchen nach Enumerable # select (auch genannt find_all):

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

Gemäß der Dokumentation wird "ein Array zurückgegeben, das alle Elemente von [in diesem Fall die Aufzählung @fathers] enthält, für die der Block nicht falsch ist".

Jordan läuft
quelle
22
Oh! Du warst der erste! Meine Antwort löschen und +1.
Milan Novota
20
Wenn Sie nur einen einzigen (den ersten) finden möchten, können Sie ihn @fathers.find {|father| father["age"] > 35 }stattdessen verwenden.
Leigh McCulloch
1
Ist es möglich, den Index zurückzugeben, an dem dies im ursprünglichen Array von Hashes gefunden wurde?
Ian Warner
1
@ IanWarner Ja. Ich schlage vor, die Dokumente für das Enumerable-Modul zu lesen. Wenn Sie es immer noch nicht herausfinden können, stellen Sie eine neue Frage.
Jordan läuft
Ich habe gerade diesen Index gemacht = ARRAY.index {| h | h [: code] == ARRAY ["code"]}
Ian Warner
198

Dies wird das erste Spiel zurückgeben

@fathers.detect {|f| f["age"] > 35 }
Naveed
quelle
6
Ich ziehe das vor #select- aber alles gilt für Ihren Anwendungsfall. #detectwird zurückgegeben, nilwenn keine Übereinstimmung gefunden wird, während #selectin @ Jordans Antwort zurückgegeben wird [].
TJ Biddle
13
Sie können auch findanstelle detectfür einen besser lesbaren Code verwenden
Alter Lagos
8
findkann jedoch in Schienen verwirrend werden.
user12341234
5
selectund detectsind nicht gleich, selectdurchquert das gesamte Array und detectstoppt, sobald die erste Übereinstimmung gefunden wird. WENN Sie nach EINEM Spiel @fathers.select {|f| f["age"] > 35 }.firstgegen @fathers.detect {|f| f["age"] > 35 } Leistung und Lesbarkeit suchen , gilt meine Stimme fürdetect
Naveed
35

wenn Ihr Array aussieht

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

Und Sie möchten wissen, ob in Ihrem Array bereits ein Wert vorhanden ist. Verwenden Sie die Suchmethode

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

Dies gibt ein Objekt zurück, wenn Hitesh im Namen vorhanden ist, andernfalls wird nil zurückgegeben

Hitesh Ranaut
quelle
Wenn der Name in Kleinbuchstaben geschrieben wurde "hitesh", wird der Hash nicht zurückgegeben. Wie können wir in solchen Fällen auch die Groß- und Kleinschreibung berücksichtigen?
Arjun
2
Sie können so etwas wie verwenden. array.find {| x | x [: name] .downcase == "Hitesh" .downcase}
Hitesh Ranaut