Ruby 2.0.0 Array #bsearch行为

jsh*_*ort 19 ruby arrays binary-search bsearch

我注意到,从Ruby 2.0.0开始,数组类有一个bsearch我正在测试的方法,而且我没有得到我期望的行为.为什么它返回2和5的值,但是nil-1,1和4?

arr_in = [-1, 1, 2, 4, 5]

arr_in.bsearch { |x| x == 3 }   #=> nil
arr_in.bsearch { |x| x == -1 }  #=> nil
arr_in.bsearch { |x| x == 1 }   #=> nil
arr_in.bsearch { |x| x == 2 }   #=> 2
arr_in.bsearch { |x| x == 4 }   #=> nil
arr_in.bsearch { |x| x == 5 }   #=> 5
Run Code Online (Sandbox Code Playgroud)

fl0*_*00r 30

arr_in = [-1, 1,2,4,5]
arr_in.bsearch{ |x| 2 - x }
#=> 2
arr_in.bsearch{ |x| -1 - x }
#=> -1
arr_in.bsearch{ |x| 3 - x }
#=> nil
Run Code Online (Sandbox Code Playgroud)

二进制搜索使用块的结果作为提示应该选择阵列的一部分(左侧或右侧)以便在下一次迭代时进行搜索.如果块返回0,它将停止搜索.如果它返回少于0,它将会离开,否则它会正确:)

更多信息请访问 http://www.ruby-doc.org/core-2.1.1/Array.html#method-i-bsearch

UPD

好吧,让我们举个例子吧

arr_in = [-1, 1, 2, 4, 5]
arr_in.bsearch { |x| x == 3 }
Run Code Online (Sandbox Code Playgroud)

首先,我们将采用中间元素(2)并将其生成块.2 == 3将返回false,所以我们移动到数组的右侧.

我们把中间的元素[4, 5]55 == 3false

右边没有任何元素,所以我们会回来 nil

arr_in = [-1, 1, 2, 4, 5]
arr_in.bsearch { |x| x == 2 }
Run Code Online (Sandbox Code Playgroud)

首先2 == 2true.我们走到左边.

中间元素[-1, 1]是1. 1 == 2false.我们走向右边.

1中没有任何元素[-1, 1],所以我们返回最后一个返回true语句的元素2

PS:别忘了,数组应该排序;)

  • 因此,如果您需要实现与`Array#detect`相同的功能,则需要使用`array.bsearch {| x | MYVAL - x}` (3认同)

aku*_*uhn 11

我发现使用宇宙飞船运营商更直观

array.bsearch {|x| 3 <=> x }
Run Code Online (Sandbox Code Playgroud)

只需确保将x太空船放在右侧.

这也适用于字符串和任何可比较的对象<=>.

  • 这应该是公认的答案。那么就不需要编写“此方法的包装器”了。另外,我认为有必要解释一下为什么你说,“确保将‘x’放在宇宙飞船运算符‘&lt;=&gt;’的右侧……原因是在每次迭代都是左手操作数。因此,如果您想找到“3”,则需要不断与“3”进行比较,以获得正确的左、右或相等的结果。如果您将变量放入在左边(正如人们直觉所做的那样),你颠倒了比较输出,挫败了 bsearch 算法! (4认同)