从相邻值计算数组中的缺失值

时间:2010-12-31 15:01:18

标签: ruby math

给定数组

[50,30,0,0,10,0,30,60,0]

我需要用计算值替换零来创建“曲线”,例如,在10到30之间,零可以用20代替。

我一直认为必须有一个很酷的红宝石方式来做这件事,但我找不到一个。有人可以帮忙吗?解决方案需要考虑多个相邻的零,并在范围的开始和结束处为零。

任何想法?

5 个答案:

答案 0 :(得分:2)

您似乎不知道的术语是interpolation。维基百科的文章是一个很好的起点 - 究竟什么算法最适合你取决于你的问题的确切背景,所以我们不能在这里给你一个真正的答案。

答案 1 :(得分:1)

a =[50,30,0,0,10,0,30,60,0]

a.each_index{|i| a[i] = a[i-1] - ((a[i-2] - a[i-1])/2).to_i if a[i] == 0 && i > 1 }

puts a.inspect # [50, 30, 20, 15, 10, 8, 30, 60, 75]

我无法理解为什么最后一个数字可能在你的规格中是80?另外,它不适用于数组中的前两项。

答案 2 :(得分:1)

如果没有连续的零,这个难以理解的单线程就行了(list是给定的数字列表):

[0, *list, 0].each_cons(3).map { |p, x, n| x == 0 ? (p + n)/2 : x }

我认为只有Ruby 1.9。

答案 3 :(得分:0)

def find_consecutive_values( array, value=nil )
  raise "Need a value or block to find" unless value || block_given?
  start = last = nil
  ranges = []
  indices = array.each_with_index do |o,i|
    if ((block_given? && yield(o)) || o==value)
      start = i unless start
      last = i
    else
      ranges << (start..last) if start && last
      start = last = nil
    end
  end
  ranges << (start..last) if start && last
  ranges
end

def interpolate_zeros( array, round=false )
  result = array.dup
  find_consecutive_values( array, 0 ).each do |range|
    next unless range.first>0 && range.last<(array.length-1)
    before = result[range.first - 1]
    after  = result[range.last  + 1]
    diff   = after - before
    size   = (range.last - range.first + 2).to_f
    range.each_with_index do |i,idx|
      value = before + diff * (idx+1)/size
      value = value.round if round
      result[i] = value
    end
  end
  result
end

p interpolate_zeros( [0,50,30,0,0,10,0,30,60,0], true )
#=> [0, 50, 30, 23, 17, 10, 20, 30, 60, 0]

答案 4 :(得分:0)

偶然发现了这个问题。有一个红宝石宝石“插补器”,它可以做你想要的,也可能更多:

http://interpolator.rubyforge.org

这是一个简短的介绍:

http://fabianosoriani.wordpress.com/2010/02/23/ruby-interpolation-with-gem-interpolator/