Ruby 101: How to filter an Array using proc
Over at the PhRUG, a Ruby developer community based in the Philippines, we conduct code review sessions via our mailing list. A code is posted and members share alternative implementations. So far, it’s been effective and newbies and veterans alike are learning new things in Ruby. Here’s a recent code that filters an array based on several conditions.
matches = []
(0..9).each do |i|
if (i > 5) && (i % 2).zero? && (i % 3).zero?
matches << i
end
end
The first improvement made by Bong is to use ‘select’.
matches = (0..9).select {|i| (i > 5) && (i % 2).zero? && (i % 3).zero?}
What if you are going to include another condition? Of course, you can argue to simply hard code the new condition but that wouldn’t be fun
The solution by Tim and Neil is to use procs which I’m sure would make Matz very happy.
conditions = [
proc { |i| i > 5 },
proc { |i| (i % 2).zero? },
proc { |i| (i % 3).zero? }
]
elements = (1..10).to_a
matches = elements.select do |i|
conditions.all? { |c| c[i] }
end
puts matches.join(',')
We can even add this filtering to the Array class, just in case we need to use this across our application.
class Array
def matches(*conditions)
select do |i|
conditions.all? { |c| c[i] }
end
end
end
matches = elements.matches(*conditions)
puts matches.join(',')
matches = elements.matches( proc{ |i| i > 5 })
puts matches.join(',')
matches = elements.matches( proc{ |i| i > 5 }, proc{ |i| (i%3).zero? })
puts matches.join(',')