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
无效?
答案 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。你的区块恰恰相反。