Rails:平均一系列时间

时间:2013-10-09 20:57:47

标签: ruby-on-rails ruby arrays

我有一个像这样的数组:["18:45", "18:45", "18:58"]

以下是我用来平均时间的方法:

  def avg_of_times(array_of_time)
    size = array_of_time.size
    avg_minutes = array_of_time.map do |x|
      hour, minute = x.split(':')
      total_minutes = hour.to_i * 60 + minute.to_i
    end.inject(:+)/size
    "%s:%s" % avg_minutes.divmod(60)
  end

如果我在irb控制台中运行上述相同的方法,平均值就会很好,但在Rails中,它会像这样出现:18:148/3

导致此方法在rails中无法正常运行的原因是什么?

Rails version: 3.2.14
Ruby version: 1.9.3-p429

4 个答案:

答案 0 :(得分:2)

您的代码可在我的IRB控制台Rails 3.2.11Ruby 1.9.3-p448中使用。


问题是你在计算中得到一个浮点数,而这个转换为一个Rational对象(解决无穷小的.33小数)。我会试试这个:

def avg_of_times(array_of_time)
  size = array_of_time.size
  avg_minutes = array_of_time.map do |x|
    hour, minute = x.split(':')
    total_minutes = hour.to_i * 60 + minute.to_i
  end.inject(:+)/size
  "%s:%s" % avg_minutes.divmod(60).map(&:to_i)
                                  #^^^^^^^^^^^ here is the new part
end

或者像@Matt建议的那样,只需将总数分钟解决问题:

"%s:%s" % avg_minutes.round.divmod(60)

答案 1 :(得分:1)

问题不在于铁轨本身。可能某些库(可能是mathn)重新定义/以使用Rational或类似的东西。描述some workaround以避免问题。

答案 2 :(得分:1)

我相信你的问题已得到解答。这是另一种方法:

  #require 'active_support'

  a = ["18:35", "19:07", "23:09"]
  avg = a.inject {|tot, str| tot + Time.parse(str).seconds_since_midnight}/(a.size.to_f).round
  mins = avg.divmod(60).first
  hours = mins.divmod(60).first
  hours.to_s + ':' + (mins-hours*60).to_s # => "20:17"

答案 3 :(得分:1)

"%d:%02d" % avg_minutes.divmod(60)

这有两个好处:

  • 当avg_minutes是Rational对象时,它可以正常工作。
  • 它将分钟格式化为两位数。所以你得到“18:01”而不是“18:1”。