Enumerator迭代

Mix-in Enumerator获得的迭代方法

each_cons()

  1. each_cons(n) { ... } nil
  2. each_cons(n) an_enumerator

迭代容器中的每个元素,都从其开始向后取连续n个元素组成一个数组传递到语句块中。

  1. (1..10).each_cons(3) { |a| p a }
  2. ## 输出:
  3. =begin
  4. [1, 2, 3]
  5. [2, 3, 4]
  6. [3, 4, 5]
  7. [4, 5, 6]
  8. [5, 6, 7]
  9. [6, 7, 8]
  10. [7, 8, 9]
  11. [8, 9, 10]
  12. =end

each_slice()

  1. each_slice(n) { ... } nil
  2. each_slice(n) an_enumerator

每次从容器中取出3个n个元素组成数组传递到语句块中。

  1. (1..10).each_slice(3) { |a| p a }
  2. ## 输出:
  3. =begin
  4. [1, 2, 3]
  5. [4, 5, 6]
  6. [7, 8, 9]
  7. [10]
  8. =end

each_with_index()

  1. each_with_index { |obj, i| block } enum
  2. each_with_index an_enumerator

迭代容器每个元素,将元素和其对应的index传递给语句块中的两个变量。

  1. hash = Hash.new
  2. %w(cat dog wombat).each_with_index { |item, index|
  3. hash[item] = index
  4. }
  5. hash # {"cat"=>0, "dog"=>1, "wombat"=>2}

with_index()

  1. e.with_index(offset = 0) {|(*args), idx| ... }
  2. e.with_index(offset = 0)

迭代容器每个元素,将元素和对应的index传递给语句块中的两个变量。可以指定参数offset,使得传递给语句块的index变量从offset开始(即传递每个原始index加上offset后的值)。默认,offset=0,等价于each_with_index。

  1. a = %w(a b c d e)
  2. a.each.with_index do |x,idx|
  3. p "index: #{idx}, value: #{x}"
  4. end
  5. ## 输出:
  6. =begin
  7. "index: 0, value: a"
  8. "index: 1, value: b"
  9. "index: 2, value: c"
  10. "index: 3, value: d"
  11. "index: 4, value: e"
  12. =end
  13. a.each.with_index(2) do |x,idx|
  14. p "index: #{idx}, value: #{x}"
  15. end
  16. ## 输出:
  17. =begin
  18. "index: 2, value: a"
  19. "index: 3, value: b"
  20. "index: 4, value: c"
  21. "index: 5, value: d"
  22. "index: 6, value: e"
  23. =end

each_with_object()

  1. each_with_object(obj) { |(*args), memo_obj| ... } obj
  2. each_with_object(obj) an_enumerator

实现类似于reject/reduce的功能。迭代每个元素,然后将元素传递给语句块中的变量,于此同时,还会指定一个obj参数对象作为memo_obj变量的初始值,最后经过语句块的操作之后,返回obj最初引用的对象。

必须注意,obj应该传递可变对象,并保证在语句块中没有改变obj对象的引用,否则each_with_object将总是返回初始值。见下面示例分析。

  1. evens = (1..10).each_with_object([]) { |i, a| a << i*2 }
  2. #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

上面的例子中,迭代Range容器中的每个元素并将之传递给语句块中的变量i,同时传递一个初始空数组对象给语句块中的变量a,这就像是在语句块中初始化了一个空数组。然后,每次迭代过程中都将i乘2后放入数组的尾部。最后返回这个数组对象a。

再比如下面的例子中,传递初始字符串对象"x",两个语句块都将每次迭代的字母追加到这个字符串对象的尾部,但是结果却不同。

  1. a = ("a".."c").each_with_object("x") {|i,str| str += i}
  2. b = ("a".."c").each_with_object("x") {|i,str| str << i}
  3. p a # "x"
  4. p b # "xabc"

这是因为,虽然str += i每次都会创建新的对象并赋值给str,使得str从引用原有的字符串对象"x"改变为引用另一个新对象,每次迭代都会改变引用目标,使得最后返回时,只能返回最初始的字符串对象"x"。

str << i的方式是直接在原字符串上追加字母的,str所引用的对象一直都未改变,最后返回的原始对象也是更改后的。

而对于数值对象来说,它是不可变对象,意味着操作这个对象一定会返回一个新对象,而且下面也使用sum += i的方式,它本身就是返回新对象的。于是,下面的例子将总是返回初始数值对象0。

  1. a = (1..10).each_with_object(0) {|i, sum| sum += i}
  2. p a # 0

要实现数值相加,可以使用reduce/inject()来实现。

  1. a = (1..10).inject(:+)
  2. p a # 55
  3. a = (1..10).inject {|sum, x| sum + x}
  4. p a # 55

each_entry()

传递容器中每个元素给语句块,并从语句块中yield一个新数组返回。

  1. class Foo
  2. include Enumerable
  3. def each
  4. yield 1
  5. yield 1, 2
  6. yield
  7. end
  8. end
  9. Foo.new.each_entry{ |o| p o }
  10. ## 输出:
  11. =begin
  12. 1
  13. [1, 2]
  14. nil
  15. =end

Ruby Enumerator的各种迭代的更多相关文章

  1. ruby Enumerator::lazy

    当一个很大的数组或集合需要做循环操作的时候,一次性把数据放到内存会有很大弊端.这时lazy就派上用场了.Float::INFINITY 是无穷大意思 举个例子 取出1到无穷大对7整除余数为0的前10个 ...

  2. Ruby系列文章

    安装Ruby.多版本Ruby共存.Ruby安装慢问题 Ruby语言的一些杂项 Ruby中的常量:引号.%符号和heredoc Ruby中的数值 Ruby字符串(1):String基本用法 Ruby字符 ...

  3. Ruby小白入门笔记之<个人记录档>

    书写缘由 快两年的JAVA开发,因为来到一家新公司,产品需要用Ruby开发,故此才有了这从头开始,一入编程深似海啊...... 因为入门时是JAVA,所以理念跟规范早已形成,故此感觉突然采用Ruby编 ...

  4. ruby迭代器iterator和枚举器Enumerator

    编写自定义的迭代器 The defining feature of an iterator method is that it invokes a block of code associatedwi ...

  5. ruby迭代起基础

    “循环”会用在程序中的各种地方.而在循环的地方善用“迭代器”,则是熟练进行Ruby程序设计的重要关键. 不过,迭代器确实有比较抽象的地方,语法也有点怪异(尤其是yield的用法),光是依靠文字说明.看 ...

  6. 使用 Capistrano 和写作 Ruby 迭代边缘部署

    想边自己写ruby代码,边部署随时能够到处查看,heroku域名又不友好,速度在国内又慢.于是乎想起来capistrano,于是学起 ... capistrano 一点入门认知 https://www ...

  7. javascript语言扩展:可迭代对象(5)

    文章1-4篇说的都是js中的可迭代对象,下面让我们看看ruby中的等价物. 不可否认,ruby中对于迭代器和生成器的语法都相当简洁:ruby从一开始就有一个简洁的基因,而js后来的不断扩充使得其有些语 ...

  8. Ruby数组(1):基本用法

    数组 Ruby中的数组是一个容器,数组中的每个元素都是一个对象的引用. 注意,Array类中包含了Enumerable模块,所以Enumerable中的方法也都能使用,例如Enumerable中的re ...

  9. Ruby数组方法整理

    数组方法整理 方法列表: all().any().none()和one():测试数组中的所有或部分元素是否满足给定条件.条件可以是语句块中决定,也可以是参数决定 append():等价于push() ...

随机推荐

  1. Address already in use: make_sock: could not bind to address 0.0.0.0:80

    网上查了很多资料都是要杀进程,但是并没有找到占用的进程. 最后解决的方案是在apache配置文件下,去掉Listen 80 即可

  2. [LeetCode] Fibonacci Number 斐波那契数字

    The Fibonacci numbers, commonly denoted F(n) form a sequence, called the Fibonacci sequence, such th ...

  3. ip锁死怎么设置ip地址

    单击电脑网络连接图标,打开网络和共享中心   点击本地连接   点击详细信息,即可看到IP地址.子网掩码.默认网关.DNS服务器信息   再点击本地连接状态下的属性   找到Internet 协议版本 ...

  4. 30、vue 过滤器(filters)

    filter Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化.过滤器可以用在两个地方:双花括号插值和 v-bind 表达式 (后者从 2.1.0+ 开始支持).过滤器应该被添加在 Ja ...

  5. lua语言自学知识点----Lua与.Net相互调用

    知识点: LuaInterface作用是用来完成Lua与C#的相互调用. LuaInterface核心库:1.luainterface.dll 用于C#读取lua(放在bin目录同级) 2.luane ...

  6. Java作业 十一(2017-11-13)

    /*关键字*/ package com.baidu.www; abstract class A { private String name; public A(String name) { this. ...

  7. 一·PTA实验作业

    本周要求挑选3道题目写设计思路,调试过程.设计思路用伪代码描述.题目选做要求: 顺序表选择一题(6-2,6-3,7-1选一题) 单链表选择一题(6-1不能选) 有序表选择一题 一.题目 6-3 jmu ...

  8. 依赖注入[8]: .NET Core DI框架[服务消费]

    包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.当需要消费某个服务实例的时候,我们只需要指定服务类型调用IServicePr ...

  9. vux 项目的构建

    一:vux安装 # 安装vuxcnpm install vux --save   # 安装vux-loadercnpm install vux-loader --save-dev   # 安装less ...

  10. Android OpenGL ES 开发(六): OpenGL ES 添加运动效果

    在屏幕上绘制图形只是OpenGL的相当基础的特点,你也可以用其他的Android图形框架类来实现这些,包括Canvas和Drawable对象.OpenGL ES为在三维空间中移动和变换提供了额外的功能 ...