2

我有一个像这样的数组:["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

4 回答 4

2

您的代码在我的 IRB 控制台中运行,Rails 3.2.11并且Ruby 1.9.3-p448.


问题是你在计算中得到了一个浮点数,这个浮点数变成了一个 Rational 对象(解决无穷无尽的 0.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)
于 2013-10-09T21:13:31.943 回答
1

问题不是轨道本身。可能某些库(可能是mathn)重新定义/使用Rational或类似的东西。那里描述了一些解决方法以避免问题。

于 2013-10-09T21:05:59.820 回答
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"
于 2013-10-09T21:22:16.170 回答
1

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

这有两个优点:

  • 它在 avg_minutes 是一个Rational对象时起作用。
  • 它将分钟格式化为两位数。所以你得到“18:01”而不是“18:1”。
于 2013-10-09T21:30:18.100 回答