`
free_dem
  • 浏览: 1926 次
  • 性别: Icon_minigender_2
  • 来自: 长沙
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

在Ruby中实现迭代器

阅读更多
初学Ruby时,对它的迭代器一知半解,这两天在李刚的Ruby on Rails敏捷开发最佳实践中看到这方面很详细的讲解,才明白在Ruby中实现迭代器原来是件很简单的事情。现在把我的理解写出来作为一个纪录。


所谓迭代器,实际上就是一个能接受代码块的方法。对于迭代器方法而言,它能接受一个代码块作为参数。
下面定义一个Apple类,在该Apple类中,定义一个迭代器,该迭代器负责输出该Apple实例的三个实例变量。下面是Apple类的代码:
# 定义一个Apple类 
class Apple 
    # 定义Apple类的构造器 
    def initialize(name, color, weight) 
        @name = name; 
        @color = color; 
        @weight = weight; 
end 
    # 使用存储器定义了三个属性 
    attr :name 
    attr :color 
    attr :weight 
    # 定义一个show方法,该show方法可以作为Apple类的迭代器 
    def show 
        yield :name , @name 
        yield :color , @color 
        yield :weight , @weight 
    end 
end 
# 创建一个Apple实例 
apple = Apple.new("红苹果" , "红色" , "0.4") 
# 使用apple的show迭代器 
apple.show do |name , value| 
    puts "这个苹果的" + name.to_s + "变量值是:"  + value.to_s 
end 
上面的代码定义了一个Apple类,在该Apple类里定义了一个show方法,从表明上看,该show方法与普通方法并没有太大的不同,但在show方法里包含了yield调用,这表明该方法可以接受代码块参数——一个可以接受代码块参数的方法就是迭代器。
运行上面的方法,看到如下结果:
引用
这个苹果的name变量值是:红苹果
这个苹果的color变量值是:红色
这个苹果的weight变量值是:0.4

从上面运行结果中可以看出,通过使用迭代器可以非常方便地遍历某个实例的内部变量。

根据上面的执行过程,可发现了迭代器方法和块之间有如下传递关系:块被当成一个特殊参数传给迭代器方法,而迭代器方法内部在使用yield调用代码块时可将参数值传入块。

代码块也可以返回一个结果给调用它的方法。这个块中的最后一个表达式的值将会返回给方法,Array中的find方法就是这样工作的,下面就是Array中定义的find方法。
class Array 
    # 为Array增加一个find方法 
    def find 
        # 使用for循环迭代数组的所有数组元素 
        for i in 0...size  
            value = self 
            # yield调用时将数组元素值传入代码块 
            # 调用结束后将代码块的返回值(boolean值)传回该方法体 
            return value if yield value 
        end  
        return nil  
    end  
end 
# 使用数组的find方法 
puts [1, 3, 5, 7, 9].find {|v| v * v > 30 } 
在上面的代码中有一个值得注意的地方:因为Ruby是动态语言,因此当定义Array类时,是为系统的Array类增加一个find方法,而不是覆盖系统的Array类。
在上面的find方法定义中,方法体内将数组元素依次传入指定的块,如果这个块返回true,则这个方法返回当前对应的元素值;如果没有符合的值,则返回nil。
通过上面的迭代器,可以发现迭代器的优势:Array类只做自己应该做的——访问数组元素,而对数组元素所做的处理,则包含在代码块中,并允许动态指定!
实际上,迭代器的功能就是一种回调!迭代器方法所属的类只负责遍历需要遍历的元素,而对元素所做的处理则通过回调代码块来实现。
Ruby中的容器对象(如数组、Range和Hash对象等)都包含了两个简单的迭代器,分别是each和collect。each可以认为是最简单的迭代器,它会对集合的每个元素调用块。
看如下用法:
["Hello", "Ruby" , "Rails"].each do |value| 
    puts "数组元素的值是 " + value 
end 

上面的迭代器each负责迭代数组中的每个元素,把该元素的值传入代码块。
执行上面的程序,看到如下运行结果:
引用
数组元素的值是 Hello
数组元素的值是 Ruby
数组元素的值是 Rails
另一个迭代器是collect,它跟each类似,将容器中的元素传递给一个块,在块中处理后返回一个包含处理结果的新数组。
看如下代码:
a = ["Hello", "Ruby" , "Rails"].collect do |value| 
    # 把每个数组元素的字母全部大写 
    value.upcase 
end 
p a 
执行上面的程序,看到如下运行结果:
引用
["HELLO", "RUBY", "RAILS"]
分享到:
评论

相关推荐

    js 数组实现一个类似ruby的迭代器

    ·基本实现 ·在迭代中引用原来的对象,或者直接改变数组的值而不是返回一个新数组 ·向迭代传入无限多的参数 ·基本实现 今天突然发现js的数组处理起来真是麻烦,代码一些就是一大堆,相比起ruby的迭代器来真是逊色...

    Ruby迭代器的7种技巧分享

    二、依次打印1..9,在ruby中的方法就更多了,这里用比较简单的方式来实现,如下: 代码如下: (1..9).each{|i| print i,” “} 三、打印1..9中比7要小的数值,如下: 代码如下: 1.upto(9){|i| print i,” ” if i &...

    Ruby中Block和迭代器的使用讲解

    可以用Block实现回调(但它比Java的匿名内部(anonymous inner)类更简单),传递一组代码(但它远比c的函数指针灵活),以及实现迭代器。 Block只是在花括号或者do…end之间的一组代码。 {puts Hello} #this is a ...

    rgl:RGL是用于Ruby中图形数据结构和算法的框架

    Ruby图形库(RGL) RGL是用于图形数据结构和算法的框架。... 在Ruby中,可以使用其他技术来主要使用mixin和迭代器来表达算法和数据结构的通用特征。 BGL文档提到了三种实现通用性的方法: 算法/数据结

    python 使用cycle构造无限循环迭代器

    源码里我们可以看到它实现了__iter__和__next__的魔术方法,说明它既是可迭代对象也是一个迭代器,我们可以使用for循环和next()方法去操作它 我们先来看看以普通的方式去遍历一个列表 li = ['python', 'java', 'c',...

    well-grounded-rubyist-book-notes:我在Jupyter Lab(Ruby内核2.7.0)中实现的“ The Well-Grounded Rubyist”(Black&Leo)的工作笔记。

    类和方法查找method_missing 类和模块设计/命名介绍范围方法访问规则顶级方法有条件的执行循环迭代器和代码块错误处理与异常文字构造函数句法糖爆炸方法和危险转换方式布尔状态和对象...和零比较两个对象检查对象...

    square_array-ruby-apply-000

    使用迭代器并实现自己的逻辑,不要使用.each以外的任何内置数组方法(例如.collect , .inject )。 您可以问自己几个问题: 在数组上调用.each的返回值是多少? 如何在数组的每个元素上进行操作,还如何收集或存储...

    Viewpoint:用于Microsoft Exchange Web服务(EWS)的Ruby客户端访问库

    博客: : 在LinkedIn中添加我: : 在#ruby-lang(zenChild)的irc.freenode.net上找到我特征1.0的新功能SOAP后端现在仅依赖于Nokogiri。 在1.0版之前,Viewpoint在后端进行了许多迭代,包括SOAP4r和Handsoap。 ...

    learntoprogram:我在 Chris Pine 的《学习编程》第二版中工作时的代码片段

    rand 函数模块介绍第07章-流量控制分支、循环和逻辑第08章数组和迭代器数组、数组方法和迭代简介第09章 - 编写你自己的方法定义方法方法参数变量范围返回值第 10 章 - 递归递归简介创建排序算法重新实现排序不区分大...

    Programming-univbasics-4-square-array-online-web-prework

    申请while遍历数组要构建此方法,请在while使用迭代器并实现自己的逻辑。 仅使用while , Array和该解决方案的任何其他先前讨论的方法。 不要使用Ruby文档或互联网来查找您可能还不了解的内置方法或代码。 例子: ...

    square_array-v-000

    使用迭代器并实现自己的逻辑,不要使用.each以外的任何内置数组方法(例如.collect , .inject )。 您可以问自己几个问题: 在数组上调用.each的返回值是多少? 如何在数组的每个元素上进行操作,还如何收集或...

    square_array-001-prework-web

    使用迭代器并实现自己的逻辑,不要使用.each以外的任何内置数组方法(例如.collect , .inject )。 您可以问自己几个问题: 在数组上调用.each的返回值是什么? 如何在数组的每个元素上进行操作,还如何收集或...

    square_array-online-web-sp-000

    使用迭代器并实现自己的逻辑,不要使用.each以外的任何内置数组方法(例如.collect , .inject )。 您可以问自己几个问题: 在数组上调用.each的返回值是什么? 如何在数组的每个元素上进行操作,还如何收集或存储...

    square_array-online-web-prework

    使用迭代器并实现自己的逻辑,不要使用.each以外的任何内置数组方法(例如.collect , .inject )。 您可以问自己几个问题: 在数组上调用.each的返回值是什么? 如何在数组的每个元素上进行操作,还如何收集或存储...

    java笔试题算法-sieve:用各种语言实现Eratosthenes筛以展示GraalVM和Truffle的强大功能

    它在无限循环中重复计算以模拟长时间运行的过程,并给GraalVM Ruby时间来预热和优化。 $ ruby ruby/sieve.rb $ graalvm/bin/ruby ruby/sieve.rb MRI Ruby 启动很快,然后变慢。 GraalVM 的初始化周期长,但一旦运行...

    awesome-roblox:用于 Roblox 游戏开发的精选库、插件和资源列表

    (待办事项:目录)脚本- 通过 Google Analytics 跟踪访问和 Lua 错误 - 资源管理器和属性窗口的 GUI 实现- 当零件被爆炸击中时将它们分成碎片库和框架 - 一个类似 Ruby 的实用程序库,用于处理迭代器、表、数组和...

    mac_address_eui48:代表MAC地址的类的实现(IEEE EUI48标识符)

    lookup.rb:解析MAC地址的OUI图书馆MacAddressEui48 :: MacAddress 从整数初始化,MacAddress的字符串比较运算符在一系列MacAddress上进行迭代测试广播地址标记测试:本地管理,多播,... MacAddressEui48 :: ...

    inject-rewrite:创客学院

    ##第 2 周结束挑战(第一部分):注入-重写这个 repo 构成了周末挑战的一半,... 它的工作原理是初始化一个“累加器”对象,该对象遍历对象中的每个元素并在每次迭代时执行计算(重置累加器以在下一个元素上使用)。

    类hackernews源码iNews.zip

    Pagon框架已实现自动XSS处理的,只要开启了safe_query 的选项,在模板渲染的过程中会自动做XSS过滤。数据库方面使用的一个paris库,它本身使用PDO来处理SQL,PDO本身会对数据进行转义处理再存入。 性能其实是个很泛...

Global site tag (gtag.js) - Google Analytics