Как создать бесконечное число времен?

Я хочу, чтобы объект расширял Enumerable в Ruby, чтобы он был бесконечным списком понедельников (например).

Таким образом, получится: 29 марта, 5 апреля, 12 апреля и т. д.

Как я могу реализовать это в Ruby?


person Alex Baranosky    schedule 25.03.2010    source источник


Ответы (4)


В 1.9 (и, возможно, в предыдущих версиях, использующих backports) вы можете легко создать перечислитель:

require 'date'

def ndays_from(from, step=7)
  Enumerator.new {|y|
    loop {
      y.yield from
      from += step
    }
  }
end

e = ndays_from(Date.today)
p e.take(5)
#=> [#<Date: 2010-03-25 (4910561/2,0,2299161)>, #<Date: 2010-04-01 (4910575/2,0,2299161)>, #<Date: 2010-04-08 (4910589/2,0,2299161)>, #<Date: 2010-04-15 (4910603/2,0,2299161)>, #<Date: 2010-04-22 (4910617/2,0,2299161)>]
person Mladen Jablanović    schedule 25.03.2010
comment
Хорошее решение! Я подтверждаю, что это будет работать на Ruby 1.8.6+ с backports :-) - person Marc-André Lafortune; 25.03.2010

Сохраните Date как переменную экземпляра, инициализированную понедельником. Вы должны реализовать метод each, который увеличивает сохраненную дату на 7 дней, используя date += 7.

person Nick Moore    schedule 25.03.2010
comment
это может быть самое простое решение. Спасибо. - person Alex Baranosky; 25.03.2010

Вы можете что-то сделать, расширив Date...


#!/usr/bin/ruby

require 'date'

class Date
  def current_monday
    self - self.wday + 1
  end

  def next_monday
    self.current_monday + 7
  end
end

todays_date = Date.today
current_monday = todays_date.current_monday
3.times do |i|
  puts current_monday.to_s
  current_monday = current_monday.next_monday
end

2010-03-22
2010-03-29
2010-04-05
2010-04-12

... с обычными предупреждениями о расширении базовых классов, конечно.

person the Tin Man    schedule 25.03.2010
comment
Мне особенно нравится метод current_monday в этом - person Nick Moore; 26.03.2010

Вы можете расширить класс Date с помощью метода nw mondays

class Date
  def self.mondays(start_date=Date.today, count=10)
    monday = start_date.wday > 1 ? start_date - start_date.wday + 8 : start_date - start_date.wday + 1
    mondays = []
    count.times { |i| mondays << monday + i*7}
    mondays
  end
end

Date.mondays по умолчанию возвращает массив понедельников с 10 элементами от ближайшего понедельника до Date.today. Вы можете передать параметры:

Date.mondays(start_date:Date, count:Integer)

start_date - начальная точка для поиска ближайшего числа понедельников - количество понедельников, которые вы ищете

IE:

Date.mondays(Date.parse('11.3.2002'))
Date.mondays(Date.parse('11.3.2002'), 30)
person fl00r    schedule 25.03.2010