Ruby:计算时间数组的平均值

5

我在我的Array类中有以下方法:

class Array
  def avg
    if partial_include?(":")
      avg_times
    else
      blank? and 0.0 or (sum.to_f/size).round(2)
    end
  end

  def avg_times
    avg_minutes = self.map do |x|
      hour, minute = x.split(':')
      total_minutes = hour.to_i * 60 + minute.to_i
    end.inject(:+)/size
    "#{avg_minutes/60}:#{avg_minutes%60}"
  end

  def partial_include?(search_term)
    self.each do |e|
      return true if e[search_term]
    end
    return false
  end
end

这在处理普通数字数组时非常好用,但是可能会有一些情况需要处理时间数组。
例如:[18:35, 19:07, 23:09] 有没有办法计算时间对象数组的平均值呢?

4
那个字符串是以那种格式呈现的,还是一个日期时间对象? - hirolau
你可以调用 to_i 方法来获取和并进行除法运算。如果您先减去一个偏移量,那么速度会更快,因为您不需要处理 Bignum - user684934
它们是否会混合使用,还是永远只有数字或时间? - Michael Berkowski
@hirolau - 它们是字符串。 - dennismonsewicz
1
现在的代码可以将partial_include?(":")替换为self.first[':'],然后删除partial_include?方法。 - hirolau
显示剩余3条评论
2个回答

4

所以,您需要定义一个函数,可以计算格式为字符串的时间的平均值。将数据转换为分钟,计算所有分钟的平均数,然后再转回时间格式。

我会这样做:

a =  ['18:35', '19:07', '23:09']

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
  "#{avg_minutes/60}:#{avg_minutes%60}"
end

p avg_of_times(a) # = > "20:17"

当您调用函数时,您需要检查数组中的任何/所有项目是否被格式化为时间。可以使用正则表达式。


当我运行它时,我的输出值为“847/45:148/3” - 我更新了我的Array类的新版本。 - dennismonsewicz
这在我使用的最新版本的Ruby中很好用。如果您跳过最后一行,您是否会得到正确的分钟数?(例如上面的1217?)如果是,则只需编写自己的“将分钟转换为小时和分钟”的行。 - hirolau
嗯...是的,我正在运行Ruby 1.9.3。 - dennismonsewicz
将最后一行改为 "%s:%s" % avg_minutes.divmod(60) 如何?http://ruby-doc.org/core-1.9.3/Numeric.html#method-i-divmod - hirolau
谢谢!这个方法非常有效!奇怪的是,我有另一个开发者使用的是 Ruby 1.9.3-p329,它也按预期工作了。 - dennismonsewicz
这似乎是Rails的问题。 - dennismonsewicz

1

分别计算小时和分钟的平均值

以下是我们正在使用的简单方法:

def calculate_average_of_times( times )
  hours   = times.collect{ |time| time.split( ":" ).first.to_i }  # Large Arrays should only
  minutes = times.collect{ |time| time.split( ":" ).second.to_i } # call .split 1 time.

  average_hours   = hours.sum / hours.size
  average_minutes = ( minutes.sum / minutes.size ).to_s.rjust( 2, '0' ) # Pad with leading zero if necessary.

  "#{ average_hours }:#{ average_minutes }"
end

并且展示它如何与您提供的24小时时间Array一起工作,转换为Strings

calculate_average_of_times( ["18:35", "19:07", "23:09"] )
#=> "20:17"

感谢@matt-privman在此方面提供的帮助和灵感。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接