簡體   English   中英

Ruby查找范圍內的出現次數

[英]Ruby find number of occurance within range

我有以下數據,其中每一行告訴我一個過程的開始和結束時間。

我想知道從12:20:00到14:00:00,步長為5分鍾,我想知道每個時間實例有多少個進程在運行。 例如,有2個和1個進程分別在12:30和12:35運行。

我想在Ruby 1.8中實現此功能,而最有效的Rubyies方法是什么?

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

您可以嘗試以下代碼(在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'變量或StringIO。

如果將值轉換為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)
}

這是幾個簡單的對象,它們可以對應該計算您所需要的內容進行建模。 這為您提供了一個界面的開始,您可以根據需要使用它來執行更復雜的邏輯。

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

這是一個比其他發布的答案更適合於大量啟停對或時間步長的解決方案(假設您想知道每個時間步長中正在運行的進程數,而不僅僅是選定的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將保留每個時間步驟中正在運行的進程數。 如果需要提供一個不錯的接口,可以在其周圍放置一個對象包裝器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM