Ruby查找范围内的出现次数

时间:2012-02-03 12:44:35

标签: ruby

我有以下数据,每行告诉我一个过程的开始和结束时间。

我想知道从12:20:00到14:00:00,步骤为5分钟,我想知道每个时间点运行的进程数。例如,有2个和1个进程分别在12:30和12:35运行。

我想在Ruby 1.8中实现这一点,有效的Rubyiest方法是什么?

12:28:08, 12:33:29
12:28:20, 12:33:41
12:32:32, 12:32:44
12:36:56, 12:42:31
13:08:55, 13:09:08
14:09:00, 14:09:12
14:59:19, 15:04:37
15:41:40, 15:41:52

(评论) Ps:我已经有一个数组用于开始时间,sTime和结束时间,eTime。我想做这样的事情:

(sTime..eTime).step($time_interval) do |cTime|  # Current Time
      cnt = 0
      (0..(sessionstarttime.length-1)).each {|i| if cTime.between? (sessionstarttime[i], sessionendtime[i]); cnt += 1}
      printf "%s, %d\n", cTime.strftime("%d/%m/%Y %H:%M:%S"), cnt
    end

4 个答案:

答案 0 :(得分:0)

您可以尝试使用此代码(在1.9上开发,但也适用于1.8):

a = %Q{
12:28:08, 12:33:29
12:28:20, 12:33:41
12:32:32, 12:32:44
12:36:56, 12:42:31
13:08:55, 13:09:08
14:09:00, 14:09:12
14:59:19, 15:04:37
15:41:40, 15:41:52
}

start = '12:20:00'
stop = '14:00:00'

require 'stringio'

def time_to_sec(time)
  a = time.split(':').map(&:to_i)
  a[0] * 3600 + a[1] * 60 + a[2]
end

def sec_to_time(sec)
  h, n = sec.divmod 3600
  m, s = n.divmod 60
  "%02d:%02d:%02d" % [h, m, s]
end

rows = StringIO.new(a).read.delete(",").split("\n").reject{ |i| i.empty? }.map do |range|
  range.split.map{ |time| time_to_sec(time) }
end

ranges = rows.map{ |i| i[0]..i[1] }

(time_to_sec(start)..time_to_sec(stop)).step(5*60) do |time|
  cnt = ranges.count{|i| i.include? time}
  puts "#{sec_to_time(time)}: #{cnt}"
end

当然你不需要' a'如果使用真实文件,则为variable或StringIO。

答案 1 :(得分:0)

如果您将值转换为Time对象(请注意,我假设此示例的日期为2000-01-01),您可以执行以下操作:

a= [ 
    { :s=> Time.utc(2000, 1, 1, 12, 28, 8), :e=> Time.utc(2000, 1, 1, 12, 33, 29) },
    { :s=> Time.utc(2000, 1, 1, 12, 28, 20), :e=> Time.utc(2000, 1, 1, 12, 33, 41) },
    { :s=> Time.utc(2000, 1, 1, 12, 32, 32), :e=> Time.utc(2000, 1, 1, 12, 32, 44) },
    { :s=> Time.utc(2000, 1, 1, 12, 36, 56), :e=> Time.utc(2000, 1, 1, 12, 42, 31) },
    { :s=> Time.utc(2000, 1, 1, 13, 8, 55), :e=> Time.utc(2000, 1, 1, 13, 9, 8) },
    { :s=> Time.utc(2000, 1, 1, 14, 9, 0), :e=> Time.utc(2000, 1, 1, 14, 9, 12) },
    { :s=> Time.utc(2000, 1, 1, 14, 59, 19), :e=> Time.utc(2000, 1, 1, 15, 4, 37) },
    { :s=> Time.utc(2000, 1, 1, 15, 41, 40), :e=> Time.utc(2000, 1, 1, 15, 41, 52) }
]

checkTime = Time.utc(2000, 1, 1, 12, 32, 40)

a.delete_if{|b| #b[:s] is start time, b[:e] is end time
    (b[:s] > checkTime) || (b[:e] < checkTime)
}

答案 2 :(得分:0)

以下是一些简单的对象,它们可以根据您的需要进行计算。这为您提供了一个界面的开始,您可以根据需要使用它来执行更复杂的逻辑。

require 'time'

# Object Definitions

class ProcessTimelineEntry
  def initialize(start_time, end_time)
    @start_time = start_time
    @end_time = end_time
  end

  def running_at?(time)
    time >= @start_time && time < @end_time
  end
end

class ProcessTimeline
  def initialize()
    @entries = []
  end

  def add_entry(start_time, end_time)
    @entries << ProcessTimelineEntry.new(start_time, end_time)
  end

  def process_count_at(time)
    @entries.count { |e| e.running_at?(time) }
  end
end

# Example Usage

timeline = ProcessTimeline.new

DATA.readlines.each do |line|
  start_time, end_time = line.split(', ')
  timeline.add_entry(Time.parse(start_time), Time.parse(end_time))
end

puts timeline.process_count_at(Time.parse("12:30"))
puts timeline.process_count_at(Time.parse("12:35"))


__END__
12:28:08, 12:33:29
12:28:20, 12:33:41
12:32:32, 12:32:44
12:36:56, 12:42:31
13:08:55, 13:09:08
14:09:00, 14:09:12
14:59:19, 15:04:37
15:41:40, 15:41:52

答案 3 :(得分:0)

这是一个解决方案,可以比其他发布的答案更好地扩展到大量的起止对或时间步长(假设您想知道每个时间步期间运行的进程数,而不只是1或2个选定的时间步骤):

START  = Time.utc(2000,1,1, 12,20,0).to_i
FINISH = Time.utc(2000,1,1, 14,0,0).to_i
STEP   = 60*5 # 5 minutes
result = Array.new(((FINISH-START).to_f/STEP).ceil, 0)
processes = %Q{
  12:28:08, 12:33:29
  12:28:20, 12:33:41
  12:32:32, 12:32:44
  12:36:56, 12:42:31
  13:08:55, 13:09:08
  14:09:00, 14:09:12
  14:59:19, 15:04:37
  15:41:40, 15:41:52 }

processes.each_line do |times|
  times =~ /(\d\d):(\d\d):(\d\d), (\d\d):(\d\d):(\d\d)/
  st  = Time.utc(2000,1,1, $1.to_i,$2.to_i,$3.to_i).to_i
  fin = Time.utc(2000,1,1, $4.to_i,$5.to_i,$6.to_i).to_i
  st  = START if st < START
  fin = END   if fin > END
  (st..fin).step(STEP) do |t|
    result[(t-START)/STEP] += 1
  end
end

每个时间步骤中运行的进程数将保留在result中。如果需要,可以在它周围放置一个对象包装器,以提供一个漂亮的界面。