Руби найти число вхождения в пределах диапазона - PullRequest
0 голосов
/ 03 февраля 2012

У меня есть следующие данные, где каждая строка сообщает мне время начала и окончания процесса.

Я хотел бы знать с 12:20:00 до 14:00:00 с шагом 5минут, я хотел бы знать, сколько процессов работает в каждый момент времени.Например, 2 и 1 процессы выполняются в 12:30 и 12:35 соответственно.

Я хотел бы реализовать это в Ruby 1.8, и какой эффективный Ruby-способ для этого?1006 *

(Комментарии) 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 голосов
/ 04 февраля 2012

Вот решение, которое лучше масштабируется для большого количества пар «старт-стоп» или временных шагов, чем для других опубликованных ответов (учитывая, что вы хотите знать количество процессов, запущенных во время каждого временного шага,а не только 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.Вы можете поместить объектную обертку вокруг нее, если хотите, чтобы обеспечить хороший интерфейс.

0 голосов
/ 03 февраля 2012

Если вы преобразуете значения в объект 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)
}
0 голосов
/ 03 февраля 2012

Вот пара простых объектов, которые моделируют что-то, что должно вычислить то, что вам нужно. Это дает вам старт интерфейса, который вы можете использовать для более сложной логики, если вам это нужно.

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
0 голосов
/ 03 февраля 2012

Вы можете попробовать этот код (разработанный на 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 при работе с реальными файлами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...