rubybsearch

Array#bsearch in Ruby returns nil if the 0 index value is the ONLY value that meets the condition


I provided test cases below, this is just a question to scratch my curiosity.

The ruby documentation for Array#bsearch says:

"This method returns the i-th element. If i is equal to ary.size, it returns nil."

This explanation just isn't clicking in my head yet. Can someone explain it a bit more in-depth?

def greater_than_8(ary)                                                                        
  a = ary.bsearch { |x| x.to_f > 8 }                                                           
  a.nil? || a.to_f < 8 ? "No number greater than 8" : a                                        
end                                                                                            
                                                                                               
                                                                                               
ary = [0, 4, 7, 10, 12]                                                                        
puts greater_than_8(ary)                                                                       
#=> 10                                                                                         
                                                                                               
# Shouldn't this return 14?                                                                    
ary = [14, 3, 7]                                                                               
puts greater_than_8(ary)                                                                       
#=> "No number greater than 8" 

# THERE IT IS!                                                                
ary = [14, 13, 7]                                                                               
puts greater_than_8(ary)
#=> 14
                                                                                               
ary = [8, 8, 8, 8]                                                                             
puts greater_than_8(ary)                                                                       
#=> "No number greater than 8"                                                                 
                                                                                               
ary = [8.01, 123]                                                                              
puts greater_than_8(ary)                                                                       
#=> 8.01  

ary = ["one hundred", "151", "120", 9]                                                         
puts greater_than_8(ary)                                                                       
#=> 151

Solution

  • Part of the documentation for Array#bsearch is the following requirement:

    You can use this method in two modes: a find-minimum mode and a find-any mode. In either case, the elements of the array must be monotone (or sorted) with respect to the block.

    In your example you are using find-minimum mode. From there we look at some of your inputs you've used and see if they are monotone or not.

    # Monotone increasing, allowed
    ary = [0, 4, 7, 10, 12]                                                                        
    
    # Not monotone, not allowed                                                                                            
    ary = [14, 3, 7]                                                                               
    
    # Monotone decreasing, allowed
    ary = [14, 13, 7]