2017-02-19 6 views
2

Я играю с Ruby on Codecademy и не уверен, как уменьшить это дальше. Текущий код:Использование перечислений для нескольких объектов в Ruby

group_1 = [4.1, 5.5, 3.2, 3.3, 6.1, 3.9, 4.7] 
group_2 = [7.0, 3.8, 6.2, 6.1, 4.4, 4.9, 3.0] 
group_3 = [5.5, 5.1, 3.9, 4.3, 4.9, 3.2, 3.2] 

over_4_feet = Proc.new { |height| height >= 4 } 

can_ride_1 = group_1.select(&over_4_feet) 
can_ride_2 = group_2.select(&over_4_feet) 
can_ride_3 = group_3.select(&over_4_feet) 

Интересно, как я мог бы получить что-то вроде этого:

can_ride_(1..3).each {|x| group_(x).select(&over_4_feet)} 

это возможно, когда объекты держать повторяющиеся узоры, как это сделать, чтобы использовать Enumerable метод, таким образом, ? Я не возражаю, если это регулярное выражение, но вам интересно, какой шаблон можно рекомендовать.

+0

вы смотрели на http://stackoverflow.com/questions/5349624/how-to-call-methods-dynamically-based-on-their-name – mahatmanich

+0

Пошлите Я думаю, что динамическая отправка что вы ищет ... – mahatmanich

+0

@mahatmanich не 'group _ # {x}' работает? Я помню, что видел это '#' где-то – niceman

ответ

1

Это действительно дерьмовый вопрос (один на CodeAcademy), потому что код явно не отражает реальный мир. Это умудряется тому, что определение объектов вокруг поведения является сложной задачей. Тем не менее, здесь другой подход, это чисто академический - никогда не делать этого в производстве код:

group_1 = … 
group_2 = … 
group_3 = … 

can_ride_1 = can_ride_2 = can_ride_3 = nil 

1.upto(3) do |i| 
    group = binding.local_variable_get("group_#{i}") 
    binding.local_variable_set("can_ride_#{i}", group.select { |v| v >= 4 }) 
end 

Вот еще эксплуатация этого:

eligible_riders = -> (group_num) do 
    group = binding.local_variable_get("group_#{group_num}") 
    group.select { |v| v >= 4 } 
end 

can_ride_1 = eligible_riders[1] 
can_ride_2 = eligible_riders[2] 
can_ride_3 = eligible_riders[3] 

Более подходящий способ сделать это было бы извлечь объект для представления каждого group:

class Group < Array 
    def select_eligible 
    select { |v| v >= 4 } 
    end 
end 

group_1 = Group.new [1, 2, 3, 4, 5] 
group_2 = Group.new [1, 2, 3, 4, 5] 
group_3 = Group.new [1, 2, 3, 4, 5] 

eligible = [group_1, group_2, group_3].map &:select_eligible 
can_ride_1, can_ride_2, can_ride_3 = *eligible 

Или вы можете воспользоваться этими улучшениями SPLAT используя процедурный у вас есть:

can_ride_1, can_ride_2, can_ride_3 = *[group_1, group_2, group_3].map do |g| 
    g.select &over_4_feet 
end 
+0

Да, количество танцев, необходимых для установки в строчной интерполяции, - это не выход. Все еще веселое умственное упражнение в контексте (и FWIW, проблема в том, чтобы изолировать себя на разных блочных поведении так же глупо, как и сама по себе). Благодаря! – mbb

1

Вместо того, чтобы иметь переменную для каждой группы, вы можете иметь массив групп, поэтому вы можете использовать map в другой массив, применяя ваш select в каждом элементе.

groups = [] 

groups.push [4.1, 5.5, 3.2, 3.3, 6.1, 3.9, 4.7] 
groups.push [7.0, 3.8, 6.2, 6.1, 4.4, 4.9, 3.0] 
groups.push [5.5, 5.1, 3.9, 4.3, 4.9, 3.2, 3.2] 

over_4_feet = Proc.new { |height| height >= 4 } 

can_ride = groups.map { |group| group.select(&over_4_feet) } 

puts can_ride 
+0

Переменные 'group_1',' group_2', 'group_3' являются данностями в вопросе (проверьте ссылку), поэтому почему бы не пропустить создание другой переменной и просто написать' [group_1, group_2, group_3] .map ... '? –

+0

@CarySwoveland См. Первое предложение, в котором он утверждает, что вам не нужно иметь «переменную для каждой группы». – coreyward

+0

@coreyward, да, но это меняет вопрос, нет-нет. Кроме того, решение должно работать с любым значением (массивом) для каждой из трех переменных. Это работает только с тремя литеральными массивами. Да, это плохой вопрос. –