ruby 如何创建一个无限可枚举的Times?

os8fio9y  于 2022-11-04  发布在  Ruby
关注(0)|答案(6)|浏览(140)

我希望能够在Ruby中扩展一个对象Enumerable,使其成为一个无限的星期一列表(例如)。
因此,它将产生:3月29日、4月5日、4月12日......等
如何在Ruby中实现这一点?

rjzwgtxy

rjzwgtxy1#

在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)>]
oknrviil

oknrviil2#

Date存储为示例变量,初始化为Monday。您可以实现一个each方法,该方法使用date += 7将存储的日期增加7天。

bvk5enib

bvk5enib3#

你可以通过延长日期来做些什么...


# !/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

...当然还有关于扩展基类的常见警告。

kg7wmglp

kg7wmglp4#

可以使用nw方法 mondays 扩展Date类

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将返回从最近的星期一到Date.today的包含10个元素的星期一数组。您可以传递参数:

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

start_date -查找最近星期一的起始点计数-您要查找的星期一的数量
工业工程师:

Date.mondays(Date.parse('11.3.2002'))
Date.mondays(Date.parse('11.3.2002'), 30)
62o28rlo

62o28rlo5#

module LazyEnumerable
  extend Enumerable

  def select(&block)
    lazily_enumerate { |enum, value| enum.yield(value) if 
block.call(value) }
  end

  def map(&block)
    lazily_enumerate {|enum, value| enum.yield(block.call(value))}
  end

  def collect(&block)
    map(&block)
  end

  private

  def lazily_enumerate(&block)
    Enumerator.new do |enum|
      self.each do |value|
        block.call(enum, value)
      end
    end
  end
end

...........

class LazyInfiniteDays
  include LazyEnumerable

  attr_reader :day

  def self.day_of_week
    dow = { :sundays => 0, :mondays => 1, :tuesdays => 2, :wednesdays => 
3, :thursdays => 4, :fridays => 5, :saturdays => 6, :sundays => 7 }
    dow.default = -10
    dow
  end

  DAY_OF_WEEK = day_of_week()

  def advance_to_midnight_of_next_specified_day(day_sym)
    year = DateTime.now.year
    month = DateTime.now.month
    day_of_month = DateTime.now.day
    output_day = DateTime.civil(year, month, day_of_month)
    output_day += 1 until output_day.wday == DAY_OF_WEEK[day_sym]
    output_day
  end

  def initialize(day_sym)
    @day = advance_to_midnight_of_next_specified_day(day_sym)
  end

  def each
    day = @day.dup
    loop {
      yield day
      day += 7
    }
  end

  def ==(other)
    return false unless other.kind_of? LazyInfiniteDays
    @day.wday == other.day.wday
  end
end
r8xiu3jd

r8xiu3jd6#

Ruby 2.7引入了Enumerator#produce,用于从任意块创建一个无限枚举器,这导致了一种非常优雅、非常实用的方式来实现最初的问题:

irb(main):001:0> require 'date'
=> true
irb(main):002:0> puts Date.today
2022-09-23
=> nil
irb(main):003:0> Date.today.friday?
=> true
irb(main):004:0> future_mondays = Enumerator.produce { |date|
  date = (date || Date.today).succ
  date = date.succ until date.monday?
  date
}
=> #<Enumerator: #<Enumerator::Producer:0x00007fa4300b3070>:each>
irb(main):005:0> puts future_mondays.first(5)
2022-09-26
2022-10-03
2022-10-10
2022-10-17
2022-10-24
=> nil
irb(main):006:0> _

相关问题