In Ruby, how do I check if at least 80% of elements in an array match a pattern?

202 Views Asked by At

I'm using Ruby 2.4. How do I check if at least 80% of my elements in an array match a certain pattern? I want to see if each element matches the regex

/\d\d?\s*-\s*\d\d?/
3

There are 3 best solutions below

6
On BEST ANSWER

You can use Enumerable#grep in conjunction with simple math:

array.grep(/\d\d?\s*-\s*\d\d?/).size / array.size.to_f >= 0.8

To shorten this further you can use Numeric#quo or Numeric#fdiv:

array.grep(/\d\d?\s*-\s*\d\d?/).size.quo(array.size) >= 0.8
5
On

If performance does matter, you don't need to check all the elements to know if at least 80% of them are maching a condition

With ruby 2.3 this implementation is a bit faster than the count solution and twice faster than the grep solution :

def pareto_match(array, proportion: 0.8)
  min_success= (array.count * proportion).round(4)
  max_failures= (array.count * (1 - proportion)).round(4)
  success= 0
  failure= 0
  array.each do |element|
    if yield(element)
      success+= 1
      return true if success >= min_success
    else
      failure+= 1
      return false if failure > max_failures
    end
  end
end

pareto_match(array){|e| e =~ /\d\d?\s*-\s*\d\d?/}
0
On

I would write:

(array.count{|item| item =~ /\d\d?\s*-\s*\d\d?/} / array.size) >= 0.8