Ruby Enumerator的各种迭代

Enumerator迭代

Mix-in Enumerator获得的迭代方法

  • each_cons:
  • each_slice:
  • each_with_index:
  • with_index:
  • each_with_object:
  • each_entry:

each_cons()

each_cons(n) { ... } → nil
each_cons(n) → an_enumerator

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

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

each_slice()

each_slice(n) { ... } → nil
each_slice(n) → an_enumerator

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

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

each_with_index()

each_with_index { |obj, i| block } → enum
each_with_index → an_enumerator

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

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

with_index()

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

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

a = %w(a b c d e)

a.each.with_index do |x,idx|
  p "index: #{idx}, value: #{x}"
end
## 输出:
=begin
"index: 0, value: a"
"index: 1, value: b"
"index: 2, value: c"
"index: 3, value: d"
"index: 4, value: e"
=end

a.each.with_index(2) do |x,idx|
  p "index: #{idx}, value: #{x}"
end
## 输出:
=begin
"index: 2, value: a"
"index: 3, value: b"
"index: 4, value: c"
"index: 5, value: d"
"index: 6, value: e"
=end

each_with_object()

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

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

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

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

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

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

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

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

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

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

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

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

a = (1..10).inject(:+)
p a  # 55

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

each_entry()

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

class Foo
  include Enumerable
  def each
    yield 1
    yield 1, 2
    yield
  end
end
Foo.new.each_entry{ |o| p o }

## 输出:
=begin
1
[1, 2]
nil
=end

原文地址:https://www.cnblogs.com/f-ck-need-u/p/10709707.html

时间: 2024-10-10 22:32:47

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

ruby Enumerator::lazy

当一个很大的数组或集合需要做循环操作的时候,一次性把数据放到内存会有很大弊端.这时lazy就派上用场了.Float::INFINITY 是无穷大意思 举个例子 取出1到无穷大对7整除余数为0的前10个数值. (1..Float::INFINITY).select { |x| x % 7 == 0 }.take(10).to_a 这样写的话会直接卡死,这个时候用lazy (1..Float::INFINITY).lazy.select { |x| x % 7 == 0 }.take(10).to_

列表解析

迭代器就是一个有.next()方法的对象,而不是通过索引来计数.迭代器的限制:不能回退! 使用迭代器:>>> develop = ('python','c#','ruby','php','java')>>> progarmme = iter(develop) #定义迭代器>>> progarmme.__next__() #使用迭代器方法1'python'>>> next(progarmme) #使用迭代器方法2'c#'>>

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

想边自己写ruby代码,边部署随时能够到处查看,heroku域名又不友好,速度在国内又慢.于是乎想起来capistrano,于是学起 ... capistrano 一点入门认知 https://www.evernote.com/shard/s6/sh/72a2b7c8-d531-4efc-9e16-ac82af2a92b7/e54fca8a9e7014ad87c79e7a7a5538c4 capistrano 新版的安装 http://capistranorb.com/documentation

Functional Ruby

本文是函数式Ruby编程的学习笔记. 1.Ruby中的迭代方法(如each, map)需要与Block配合使用,那么如何获得Block呢? 直接使用{}或do ... end 将Proc或Method对象转化为Block. &proc_name/&:method_name => block 获得Proc或Method对象的几种方式: 注意:对于无参方法f,可以直接用&:f将其转化为block,但对于有参方法f(如上图),需要将其显示地转化为Method对象,&meth

what&#39; s ruby?(ref: ruby编程语言)

q1: irb(main):001:0> tmp=(1..10).to_a => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] irb(main):002:0> tmp.each.class => Enumerator irb(main):003:0> tmp.select.class => Enumerator irb(main):004:0> tmp.map.class => Enumerator irb(main):005:0>

《七周七语言:理解多种编程范型》のruby课后习题答案

本系列是<七周七语言>的课后习题答案.这本书不拘泥于语法细节,而是横向比较各种编程语言(非热门)之间的编程范式. 是本对编程觉悟能有所帮助的好书,这里就不多做介绍了,感兴趣的同学不妨去看一下. 不得不说,Ruby的风格很黑客. 1. 打印字符串"Hello, world." puts "Hello, world." 2. 在字符串“Hello, Ruby.”中,找出"Ruby."所在下标. puts "Hello, Ruby

Ruby操作MongoDB(进阶)-CRUD操作

MongDB数据库的使用离不开CRUD操作.什么是CRUD,就是创建文档,读取文档信息,更新文档和删除文档. key-value键值对标记 在MongoDB的Ruby驱动中,Key_value键值多次出现.而且有时会出现语法上的巧合,这取决于在使用的Ruby版本中如何申明. 在文档创建步骤中,1.9及之后版本支持以下语法: document={name:"Tom",age:20}. 但是如果你使用的是2.2或者更高的版本,你可以用双引号将你的key包起来.如: document={&q

理解Ruby中的作用域

作用域对于Ruby以及其它编程语言都是一个需要理解的至关重要的基础知识.在我刚开始学习ruby的时候遇到很多诸如变量未定义.变量没有正确赋值之类的问题,归根结底是因为自己对于ruby作用域的了解不够,但在你看看完我的这篇文章后,相信你不会再担心会遇到这些头疼的问题. 什么是作用域? 当谈论到作用域的时候,应该马上想到变量和可见性这两个词,变量和可见性是作用域的主要内容,没错,作用域就是关于在代码的什么地方什么变量是可见的,当你充分了解了作用域后,给你一段代码,你可以轻易知道此时什么变量是可见的,

Ruby快速入门

Rb是什么 ? 交互式Ruby(IRB)为实验提供了一个shell.内置IRB shell,你可以立即一行行查看表达式的结果.该工具自带Ruby安装,所以你必须做一些额外的IRB工作无关.只需键入在命令提示符IRB和交互式Ruby会话将启动. Ruby语法: Ruby代码一般忽略空白字符,如空格和制表符,除非当他们出现在字符串. Ruby的解释分号作为语句的结尾换行符.但是,如果ruby遇到运算符,如+, - ,或在一行的末尾的反斜杠,他们的声明中表示延续. 标识符名称的变量,常量和方法. Ru