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

Posted

技术标签:

【中文标题】如何创建无限可枚举的Times?【英文标题】:How to create an infinite enumerable of Times? 【发布时间】:2011-01-31 13:23:38 【问题描述】:

我希望能够让一个对象在 Ruby 中将 Enumerable 扩展为一个无限的星期一列表(例如)。

所以它会产生:3 月 29 日、4 月 5 日、4 月 12 日……等等

如何在 Ruby 中实现这一点?

【问题讨论】:

【参考方案1】:

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

【讨论】:

不错的解决方案!我确认这将在 Ruby 1.8.6+ 上使用backports :-)【参考方案2】:

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

【讨论】:

这可能是最简单的解决方案。谢谢。【参考方案3】:

你可以通过延长 Date 来做一些事情......

#!/usr/bin/ruby 需要“日期” 上课日期 def current_monday 自我 - self.wday + 1 结尾 def next_monday self.current_monday + 7 结尾 结尾 todays_date = 日期.今天 current_monday = todays_date.current_monday 3.次做|i| 将 current_monday.to_s current_monday = current_monday.next_monday 结尾 2010-03-22 2010-03-29 2010-04-05 2010-04-12

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

【讨论】:

我特别喜欢这个中的current_monday方法【参考方案4】:

您可以使用 nw 方法扩展 Date 类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 将默认返回星期一数组,其中包含从最近的星期一到 Date.today 的 10 个元素。可以传参数:

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

start_date - 查找最近的星期一的起点 count - 您正在查看的星期一数

IE:

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

【讨论】:

【参考方案5】:
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

【讨论】:

以上是关于如何创建无限可枚举的Times?的主要内容,如果未能解决你的问题,请参考以下文章

如何让对象属性不可配置或枚举

如何在 C# 4.0 中枚举无限的整数序列?

如何从可枚举转换为特定模型

使用可枚举#select创建特定数组

干货 - 一文搞定Python 枚举

通用可选枚举函数