Ruby: bsearch 返回 nil

Ruby: bsearch returning nil

我有一个排序的数字数组,想检查数字是否在数组中。我想我应该在这里使用 bsearch 但它 return nil 即使数字存在于数组中,并且只对中间元素给出肯定的结果。

这是我测试的。

>> [1,2,3,4,5].bsearch { |value| value <=> 1}
>> nil
>> [1,2,3,4,5].bsearch { |value| value <=> 3}
>> 3

我正在使用 Ruby 版本 2.3.8

您正在查找任意模式中使用Array#bsearch

如文档所述,您的区块需要满足以下要求:

  • All positive-evaluating elements precede all zero-evaluating elements.
  • All positive-evaluating elements precede all negative-evaluating elements.
  • All zero-evaluating elements precede all negative-evaluating elements.

您的区块违反了这些要求。

让我们运行通过一个例子。在第一次迭代中,Array#bsearch 将选择中间元素,即 3 并将其传递给您的块。您的块 returns 1,这意味着您正在搜索的元素 大于 3 因此必须是 right 当前元素。所以,Array#bsearch 丢弃了数组的左半部分,我们剩下 [4, 5]。现在,Array#bsearch 再次选择“中间”元素,即 4 并将其传递给您的块。您的块 returns 1,这是一个正数,因此意味着您要查找的元素大于 4,因此必须位于数组的右半部分。因此,Array#bsearch 再次丢弃了左半部分,我们只剩下 [5]。同样,Array#bsearch5 传递给块,您的块 returns 1 这是一个正数,因此意味着我们需要向右看,除了我们已经在数组的末尾,因此我们可以得出结论,您要查找的元素不在数组中。

所以,基本上,您只是在告诉 Array#bsearch 看错地方。

我们再看看文档:

These make sense as blocks in find-any mode:

a = [0, 4, 7, 10, 12]
a.map {|element| 7 <=> element } # => [1, 1, 0, -1, -1]
a.map {|element| -1 <=> element } # => [-1, -1, -1, -1, -1]
a.map {|element| 5 <=> element } # => [1, 1, -1, -1, -1]
a.map {|element| 15 <=> element } # => [1, 1, 1, 1, 1]

This would not make sense:

a = [0, 4, 7, 10, 12]
a.map {|element| element <=> 7 } # => [-1, -1, 0, 1, 1]

所以,基本上你写的块完全就像文档明确所说的块错误,并且与文档告诉您的方法完全相反

如果您翻转块中的两个操作数,使您的块看起来像文档中的示例所说的那样,它将起作用:

[1, 2, 3, 4, 5].bsearch { |value| 0 <=> value } #=> nil
[1, 2, 3, 4, 5].bsearch { |value| 1 <=> value } #=> 1
[1, 2, 3, 4, 5].bsearch { |value| 2 <=> value } #=> 2
[1, 2, 3, 4, 5].bsearch { |value| 3 <=> value } #=> 3
[1, 2, 3, 4, 5].bsearch { |value| 4 <=> value } #=> 4
[1, 2, 3, 4, 5].bsearch { |value| 5 <=> value } #=> 5
[1, 2, 3, 4, 5].bsearch { |value| 6 <=> value } #=> nil