代码改变世界

ruby迭代器iterator和枚举器Enumerator

  youxin  阅读(1049)  评论(0编辑  收藏  举报

 

编写自定义的迭代器

The defining feature of an iterator method is that it invokes a block of code associated
with the method invocation. You do this with the yield statement. The following
method is a trivial iterator that just invokes its block twice:
def twice
 yield
  yield
end

To pass argument values to the block, follow the yield statement with a comma separated
list of expressions. As with method invocation, the argument values may
optionally be enclosed in parentheses. The following simple iterator shows a use of
yield:

def sequence(n,m,c)
    i=0
    while(i<n)
        yield m*i+c
        i+=1
    end
end
sequence(3,5,1) { |y| puts y}

下面是ruby迭代器的另一个例子,它传递两个实参给相关联的代码块,值得注意的是,这个迭代器实现在内部使用了另一个迭代器:

def circle(r,n)
n.times do |i| # Notice that this method is implemented with a block
    angle = Math::PI * 2 * i / n
    yield r*Math.cos(angle), r*Math.sin(angle)
end
end
# This invocation of the iterator prints:
# (1.00, 0.00) (0.00, 1.00) (-1.00, 0.00) (-0.00, -1.00)

使用yield关键字的确很像调用一个方法,围绕参数的圆括号是可选的,但是,他和方法调用的不同之处在于不能在yield表达式后面接代码块,你不能将一个代码块传递给另一个代码块。

如果一个方法在调用时没有相关联的代码块,那么在定义该方法时使用yield就是错误的,因为在这种情况下,将没有什么可以作为yield的目标。有时候你希望编写这样一个方法:当有相关联的代码块时就使用yield,否则将采取一些默认行为(而不是抛出一个错误)。为了做到这一点,你可以使用block_given?方法判断是否在调用该方法时带有一个代码块。block_given?及它的同义词iterator?都是Kernel的方法,因此他们表现的像全局函数一样。

复制代码
# Return an array with n elements of the form m*i+c
# If a block is given, also yield each element to the block
def sequence(n, m, c)
   i, s = 0, [] # Initialize variables
  while(i < n) # Loop n times
    y = m*i + c # Compute value
   yield y if block_given? # Yield, if block
   s << y # Store the value
  i += 1
end
s # Return the array of values
end
复制代码

sequence(3,5,1) { |y| puts y}

 

s= sequence(3,5,1)
s.each { |x| print x}

 

 

一个枚举器必须是一个Enumerable对象,其目的在于枚举其他的对象。

 

range

A..Z 范围提供了to_a,可以转成数组

('A'..'Z').to_a.each{|letter| print letter}

检验是否属于某个范围

puts ('A'..'Z').include?('r')

还可以把范围当做数组的索引,一次选择多个元素


a=[2,4,6,8,10]
puts a[1..3]

 

参考:《ruby programming》

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2013-07-04 asp.net插入sql server 中文乱码问题解决方案
2012-07-04 转:中国互联网十五年的22个创新模式
2012-07-04 保罗·格雷厄姆(Paul Graham
2012-07-04 转:二进制、八进制、十进制、十六进制之间转换
点击右上角即可分享
微信分享提示