Reputation: 16202
I am looking for a built-in Ruby method that has the same functionality as index
but uses a binary search algorithm, and thus requires a pre-sorted array.
I know I could write my own implementation, but according to "Ruby#index Method VS Binary Search", the built-in simple iterative search used by index is faster than a pure-Ruby version of binary search, since the built-in method is written in C.
Does Ruby provide any built-in methods that do binary search?
Upvotes: 40
Views: 27738
Reputation: 5125
I use bsearch
. This is how it works:
array = ['one', 'two', 'three', 'four', 'five']
search = array.sort.bsearch { |value| 'four' <=> value }
Note: binary search needs a sorted array; this adds a li'l overhead but it's fine, compared to the speed of the search.
search
will return the value four
of the array
, else nil
if it doesn't find the value.
Upvotes: 3
Reputation: 859
A lot has changed since 2011, in Ruby 2.3, you can use bsearch_index
https://ruby-doc.org/core-2.3.0/Array.html#method-i-bsearch_index
array.bsearch_index { |val| query <=> val }
Upvotes: 12
Reputation: 79562
Ruby 2.0 introduced Array#bsearch
and Range#bsearch
.
For Ruby 1.9, you should look into the bsearch
and binary_search
gems.
Other possibility is to use a different collection than an array, like using rbtree
bsearch
is in my backports
gem, but this is a pure Ruby version, so quite a bit slower. Note that a pure Ruby binary search will still be faster than a linear builtin search like index
or include?
for big enough arrays/ranges (or expensive comparisons), since it's not the same order of complexity O(log n)
vs O(n)
.
To play with it today, you can require 'backports/2.0.0/array/bsearch'
or require 'backports/2.0.0/range/bsearch'
.
Good luck!
Upvotes: 62