Reputation: 3110
I'm playing around with Ruby on Codecademy and not sure how to reduce this further. Current code is:
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)
I wonder how I could get to something like this:
can_ride_(1..3).each {|x| group_(x).select(&over_4_feet)}
Is it possible, when objects hold repeatable patterns like these do, to use an Enumerable method in this way? I don't mind if it's a regex, but curious about what pattern might be recommended.
Upvotes: 3
Views: 71
Reputation: 80041
This is a really crappy question (the one on CodeAcademy) because the code blatantly doesn't represent the real world. It's contrived to the point that defining objects around the behavior is challenging. That said, here's another approach that's purely academic — don't ever do this in production code:
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
Here's another exploitation of this:
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]
A more appropriate way of doing this would be to extract an object to represent each 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
Or you can take advantage of those splat enhancements using the proc you have:
can_ride_1, can_ride_2, can_ride_3 = *[group_1, group_2, group_3].map do |g|
g.select &over_4_feet
end
Upvotes: 1
Reputation: 1942
Instead of having a variable for each group, you can have an array of groups, so you can map
it to another array applying your select
in each element.
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
Upvotes: 1