2013-11-17 2 views
1

Я работаю над тем, что, как я думал, является простой проблемой Code Wars, но у меня возникли проблемы с использованием перечислимых средств для решения этой проблемы.Ruby - Как фильтровать массив хэшей на одно значение, а затем возвращать значение true, если другое значение соответствует вводу?

Это мой массив данных

data = [ 
    {age: 40, sex: :m}, 
    {age: 24, sex: :f}, 
    {age: 56, sex: :m}, 
    {age: 45, sex: :m}, 
    {age: 23, sex: :f} 
] 

И проблема

Напишите метод, так что он возвращает истину, если все элементы, соответствующие значения секса имеют возраст больше, чем значение, указанное.

метод должен быть чем-то вроде

def check_ages?(data, sex, older_than) 

#Select all hashes matching param(sex) and then check if remaining age values are  greater than param(older_than) returning true if so 

end 

check_ages (данные,: F, 22)? # Должен быть истинным

check_ages (данные,: м, 50)? # Должно быть ложным

Я схожу с ума, пытаясь использовать вложенные выбрать для фильтрации хэши, а если еще соответствовать значение возраста ... Вся помощь была бы оценена

PS Im относительной newbi е с рубином, уверен, что это довольно глупый вопрос ... просто не могу понять синтаксис

+1

Вот подсказка: используйте [Enumerable # все] (http://ruby-doc.org/core-2.0.0/Enumerable.html#method-i -all-3F): 'data.all? {???} '. –

+2

данные.все? {| d | d [: sex]! = sex || d [: age]> age_is_older_than} Ваше право, отлично работает :) Спасибо Cary – Conor

+0

Хорошо для вас Conner. Всегда лучше всего заниматься этим, даже если вам нужно указывать в правильном направлении. –

ответ

-1

Это немного проще, но может работать для вас здесь

def check_ages?(data, sex, older_than) 
    for p in data 
    if p[:sex] == sex 
     if !(p[:age] > older_than) 
     return false 
     end 
    end 
    end 
    return true 
end 
+0

Большое спасибо @ Кристофер Хант, я уже усложнял вещи перечислениями, которые я, очевидно, еще не понял. Удивительно, насколько простыми могут быть некоторые решения ..forest для деревьев и т. Д.) – Conor

+2

Использование инъекции здесь не кажется идиоматическим. select-> все? имеет для меня гораздо больше смысла. (Я не спускаюсь вниз, просто указывая на это.) – Chuck

+0

Вы правы, спасибо. Я не знаю, почему я включил это, но он был удален. –

3

Я думаю, что это все, что вам нужно:

def check_ages?(data, sex, older_than) 
    raise ArgumentError, "'sex' must equal ':m' or ':f'" unless [:m, :f].include? sex 
    data.all? {|h| h[:sex] != sex || h[:age] > older_than} 
end 
2
def data.all_older_than? age, sex: nil 
    (sex ? select { |e| e[:sex] == sex } : self).all? { |e| e[:age] > age } 
end 

data.all_older_than? 30 
#=> false 

data.all_older_than? 30, sex: :male 
#=> true 
+0

Слабость, я думаю: data.all_older_than? 30, sex:: female # => true, data.all_older_than? 30, sex:: none # => true.(Это наблюдение заставило меня немного изменить свой собственный ответ.) Кроме того, этот метод доступен только для этого экземпляра массива, что было бы ограничением, если мы хотели применить его в другом месте. –

1

это думаю, что это легче читать, если вы разделить логику на две части: во-первых select, то all?

def check_ages?(data, sex, older_than) 
    data.select{|person| person[:sex] == sex } 
     .all?{|person| person[:age] > older_than} 
end 
1

Кратчайший и самый простой способ

def check_ages?(data, sex, age_is_greater_than) 
    data.select { |h| h[:sex] == sex}.all? { |a| a[:age] > age_is_greater_than } 
    end