我有一个数组:
["7", "8", "11", "13", "14"]
我希望最接近的次等数为11
(如果有的话8
),或者如果这个数字不存在,那么最接近的高等数到11
(即{{1} }})。
答案 0 :(得分:12)
h = ["7", "8", "11", "13", "14"].map(&:to_i).sort.group_by{|e| e <=> 11}
h[-1].last || h[1].first # => 8
答案 1 :(得分:9)
尝试以下获取最接近值的最短方法
n = 40
a = [20, 30, 45, 50, 56, 60, 64, 80]
a.min_by{|x| (n-x).abs}
答案 2 :(得分:4)
def closest(arr, target)
return nil if arr.empty?
a = (arr + [target]).sort_by(&:to_i)
idx = a.rindex(target)
idx > 0 ? a[idx-1] : a[idx+1]
end
arr = ["11", "7", "13", "8", "11", "14"]
closest(arr, "12") #=> 11
closest(arr, "12.5") #=> 11
closest(arr, "11") #=> 11
closest(arr, "4") #=> 7
closest(arr, "7") #=> 7
修改:此处使用方法Object#to_enum,Enumerator#next和Enumerator#peek的另一种方式:
def closest(arr, target)
return nil if arr.empty?
e = arr.map(&:to_i).sort.to_enum
x = nil # initialize to anything
loop do
x = e.next
break if x > target || e.peek > target
end
x.to_s
end
对于上面的arr
:
closest(arr, 12) #=> 11
closest(arr, 12.5) #=> 11
closest(arr, 11) #=> 11
closest(arr, 4) #=> 7
closest(arr, 7) #=> 7
当枚举数位于其最后一个值时,peek
将生成StopIteration
例外。 Kernel#loop通过突破循环来处理该异常。
答案 3 :(得分:4)
另一种解决方法:
a = arr.map(&:to_i).sort #=> [7, 8, 11, 13, 14]
a.reverse.find { |e| e < 11 } #=> 8
a.find { |e| e > 11 } #=> 13
由于find
如果没有对象匹配,则返回nil
,最后两行可以通过以下方式合并:
a.reverse.find { |e| e < 11 } || a.find { |e| e > 11 }