bsearch块中的反转表达式无效

时间:2015-12-14 16:23:44

标签: ruby bsearch

ary = [1, 4, 6, 9]
(0...ary.size).bsearch { |i|
  ary[i] - 1
}                                   # => nil

1 - ary[i]                          # => 0

当代码以ary[i] - 1形式编写时,无法按预期工作。

我要做的是找到数组中数字1的索引。

但是1 - ary[i]可以正确返回数字的索引。为什么ary[i] - 1无效?

3 个答案:

答案 0 :(得分:3)

Array#bsearch用于执行二分查找以查找满足特定条件的元素。根据{{​​3}},如果您从块中返回数值,则会使用find-any mode类型的搜索。

搜索从排序数组的中心开始 - 如果块返回负值,则在前半部分继续搜索,如果块返回正值,则在数组的后半部分继续搜索。

在你使用ary[i] - 1的情况下,block返回的值总是正数,并且在数组的后半部分递归搜索 - 并且永远不会找到值1

以下是包含一些调试语句的代码:

ary = [1, 4, 6, 9]
p (0...ary.size).bsearch { |i|
  puts "Elem: #{ary[i]} Index: #{i}"
  ary[i] - 1
}

输出:

Elem: 4 Index: 1
Elem: 6 Index: 2
Elem: 9 Index: 3
nil
[Finished in 0.4s]    

答案 1 :(得分:2)

Array#bsearch返回数组的元素,而不是匹配元素的索引。

您可能希望改为使用Array#index

答案 2 :(得分:1)

如果要查找元素的索引而不是元素本身,则需要使用Array#bsearch_index。注意:这个方法是在Ruby 2.3中引入的,在撰写本文时尚未发布(它将于2015年圣诞节发布)。

Array#bsearch_index的{​​{3}}包含Yusuke Endoh的feature request,其中展示了如何基于{{Array#bsearch_index(以及实际上comment)实施3}}:

class Array
  def bsearch_index(&blk)
    return enum_for(__method__) unless blk
    (0...size).bsearch {|i| yield self[i] }
  end
end

当运行Ruby 2.3或使用上面的猴子补丁时,你可以这样做:

ary.bsearch_index(&1.method(:-))

以查找数组中1元素的索引。

它不能与

一起使用的原因
ary.bsearch_index {|el | el - 1 }

很简单:该块违反了bsearch_index(以及bsearch的合同,因为它们是相同的)。块需要返回正在搜索的索引左侧的索引的正数,正在搜索的索引的索引的负数,以及您要搜索的范围内的索引的0。你的区块恰恰相反。