我有以下数据,每行告诉我一个过程的开始和结束时间。
我想知道从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
答案 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
中。如果需要,可以在它周围放置一个对象包装器,以提供一个漂亮的界面。