【问题标题】:How to create custom iterator for Range如何为 Range 创建自定义迭代器
【发布时间】:2011-10-04 12:55:39
【问题描述】:

我想创建 Range 的一个子类,以便指定除 1 以外的步长,这样我就可以执行以下操作:

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
-1.0
-0.5
0.0
0.5
1.0
1.5
2.0
=> -1..2

我的第一次尝试没有成功:

 class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each
    self.step(step_size).each
  end

end

>> a = RangeWithStepSize.new(-1, 2, 0.5).each {|x| puts(x)}
=> #<Enumerator: [-1.0, -0.5, 0.0, 0.5, 1.0, 1.5, 2.0]:each>

RangeWithStepSize#each 似乎返回了一个有效的枚举器,但它没有枚举。知道为什么吗?

&lt;aside&gt;这可能是相关的,但我注意到没有块的 Range#step 不会返回文档中指定的枚举器;它返回一个数组:

>> Range.new(-1, 2).step(0.5).class
=> Array

数组是可枚举的,但它不是枚举器。这是文档错误吗?&lt;/aside&gt;

澄清

我想制作一个封装步长的 Range 版本,所以我可以这样做:

a = RangeWithStepSize(-1, 2, 0.5)
b = RangeWithStepSize(-1, 2, 0.25)

...所以枚举 a 会产生 0.5 的步长,而 b 会产生 0.25。

【问题讨论】:

  • p Range.new(-1, 2).step(0.5).class #=&gt; Enumerator (Ruby 1.9.2)
  • 你使用的是什么版本的 Ruby?
  • ruby --version ruby​​ 1.9.2p136(2010-12-25 修订版 30365)[x86_64-darwin10.6.0]

标签: ruby enumerator


【解决方案1】:

你知道你可以做到这一点,对吧?这里不需要继承。

(-1..2).step(0.5) do |x|
    puts x
end

您的代码只需稍作调整即可工作:

class RangeWithStepSize < Range

  attr_reader :step_size

  def initialize(start_v, end_v, step_size, exclusive = false)
    super(start_v, end_v, exclusive)
    @step_size = step_size
  end

  def each (&block)
    self.step(step_size).each(&block)
  end

end

【讨论】:

  • 是的——请注意,我在代码中使用了 step()。我想做的是创建一个记住步长的范围。
猜你喜欢
  • 2011-07-09
  • 1970-01-01
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-08-23
  • 2014-08-26
  • 1970-01-01
相关资源
最近更新 更多