Как искать в массиве хэшей по значениям хэша в ruby?

234

У меня есть массив хэшей, @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 

Как я могу найти этот массив и вернуть массив хэшей, для которого блок возвращает true?

Например:

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

Спасибо.

doctororange
источник

Ответы:

419

Вы ищете Enumerable # select (также называется find_all):

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

Согласно документации, он «возвращает массив, содержащий все элементы [в данном случае перечислимого @fathers], для которых блок не равен false».

Джордан Бег
источник
22
Ой! Вы были первым! Удаление моего ответа и +1.
Милан Новота
20
Как примечание, если вы хотите найти только один (первый), вы можете использовать @fathers.find {|father| father["age"] > 35 }вместо этого.
Ли МакКаллох
1
Можно ли вернуть индекс, где это было найдено в исходном массиве хэшей?
Ян Уорнер
1
@IanWarner Да. Я предлагаю посмотреть документы для модуля Enumerable. Если вы все еще не можете понять это, опубликуйте новый вопрос.
Джордан, бегущий
Я только что сделал этот индекс = ARRAY.index {| ч | h [: code] == ARRAY ["code"]}
Ян Уорнер,
198

это вернет первый матч

@fathers.detect {|f| f["age"] > 35 }
Навид
источник
6
Я предпочитаю это #select- но все идет за ваш вариант использования. #detectвернется, nilесли совпадений не найдено, а #selectв ответе @ Jordan вернется [].
TJ Biddle
13
Вы также можете использовать findвместо detectболее читабельного кода
Alter Lagos
8
findоднако, может быть запутанным в рельсах.
user12341234
5
selectи detectне совпадают, selectбудет проходить через весь массив, а detectостановится, как только будет найдено первое совпадение. Если вы ищете ОДИН матч @fathers.select {|f| f["age"] > 35 }.firstпротив @fathers.detect {|f| f["age"] > 35 } производительности и читабельности, мой голос заdetect
Naveed
35

если ваш массив выглядит

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

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

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

Это возвратит объект, если Hitesh присутствует в имени, иначе вернет ноль

Хитеш Ранаут
источник
Если имя было строчным "hitesh", оно не вернет хеш. Как мы можем объяснить регистр слов в таких случаях?
Арджун
2
Вы можете использовать что-то вроде. array.find {| x | х [: имя] .downcase == .downcase "Hitesh"}
Hitesh Ranaut