从数组中获取最接近的数字值

时间:2016-01-20 09:47:06

标签: ruby

我有一个数组:

["7", "8", "11", "13", "14"]

我希望最接近的次等数为11(如果有的话8),或者如果这个数字不存在,那么最接近的高等数到11(即{{1} }})。

4 个答案:

答案 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_enumEnumerator#nextEnumerator#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 }