【转】牛逼闪闪的Ruby迭代器-阿里云开发者社区

开发者社区> 余二五> 正文

【转】牛逼闪闪的Ruby迭代器

简介:
+关注继续查看

D瓜哥最近想做一个网站,另外,老早就有学习一门动态语言的想法,满足着两个条件的编程语言中,Ruby、Python是最合适的两种语言。现在Ruby on Rails如日中天,光芒万丈!所以,就选定了Ruby,从零开始学习。

  前天看了Ruby的迭代器,对于我这个只学过Java、C/C++等的人来说,绝对是眼前一亮的感觉!而且是光彩夺目:没想到迭代器还可以这么玩,太简练太方便而且特别强大!然后,D瓜哥就迫不及待的想写一篇文章给大家介绍介绍Ruby的迭代器!


迭代器简介


先简单介绍一下迭代器。

1.一个Ruby迭代器就是一个简单的能接收代码块的方法(比如each这个方法就是一个迭代器)。特征:如果一个方法里包含了yield调用,那这个方法肯定是迭代器;

2.迭代器方法和块之间有如下传递关系:块被当成一个特殊参数传给迭代器方法,而迭代器方法内部在使用yield调用代码块时可将参数值传入块;

3.实际上,迭代器的功能就是一种回调!迭代器方法所属的类只负责遍历需要遍历的元素,而对元素所做的处理则通过回调代码块来实现;

4.Ruby中的容器对象(如数组、Range和Hash对象等)都包含了两个简单的迭代器,分别是each和collect。each可以认为是最简单的迭代器,它会对集合的每个元素调用块。 collect,将容器中的元素传递给一个块,在块中处理后返回一个包含处理结果的新数组;


迭代器详解

  Ruby中的迭代器可以说五花八门,下面我们从字符串、数字、数组、Map、文件、目录等几个方面来简单介绍一下Ruby的迭代器。


字符串迭代器

  在Java中,字符串类型的数据没有迭代器。所以,如果需要“遍历”字符串,需要将字符串做一些其他处理才行。但是,在Ruby中就有。下面,我们通过代码来演示一下: 

代码如下:

1
2
3
4
5
str = "abc"
str.each_byte {|c| printf ">%c", c};  #
# 输出如下:(为了和代码区别,D瓜哥在输出前面人为地加了#。)
# 以下的输出展示,处理方式相同。
#>a>b>c

each_byte 是字串中用于处理每个字节的迭代器。每个字节都会代入块参数 c 中。


Ruby中,不仅有用于字节的迭代器,还有用于每行的迭代器。示例如下:

代码如下:

1
2
3
4
5
6
str = "abc\nefg\nhijk"
str.each_line{|l| print l}
# 输出如下:
#abc
#efg
#hijk

怎么样,是不是被Ruby简练但强大的迭代器所折服?!好戏还在后面,接着向下看。


数字迭代器

  在Ruby中,“一切皆为对象”,甚至数字也是对象。这点和Java不一样。所以,对字的迭代器,对于我这个Java程序猿也是闻所未闻。让我们写两个示例,管窥一二。

  第一个场景:对某段代码进行N(比如5)次操作。在Java中,需要写个循环,但是在Ruby中,只需要调用一下times方法即可。代码如下:

代码如下:

1
2
3
4
5
6
7
5.times {print "I love http://www.jb51.net/ \n"# 真的就这么简单
# 输出如下:
#I love http://www.jb51.net/
#I love http://www.jb51.net/
#I love http://www.jb51.net/
#I love http://www.jb51.net/
#I love http://www.jb51.net/

第二个场景:求1到5的数字之和。这个也特别简单:

代码如下:

1
2
3
sum = 0
(1..5).each {|i| sum += i}
print "Sum="+sum.to_s

如果使用upto函数,还可以这样写:

代码如下:

1
2
3
sum = 0
1.upto(5) {|x| sum += x }
print "Sum="+sum.to_s

 有时,我们的步进不一定是1,可能是2,例如奇数求和。这种情况下,可以使用step函数。代码如下:

1
2
3
4
5
sum = 0   
1.step(52do |y| # step函数第二个参数是步进。
   sum += y   
end  
print "Sum="+sum.to_s

感觉有点扯远了。下面,我们讲讲数组相关的迭代器。


数组迭代器

见识过了数字相关的迭代器,我们再看看数组相关的迭代器。

第一个场景:便利数组并输出每个元素。直接上代码:

代码如下:

1
2
3
4
5
6
7
8
languages = ['Ruby''Javascript''Java']
languages.each_with_index do |lang, i|
    puts "#{i}, I love #{lang}!"
end
#输出如下:
#0, I love Ruby!
#1, I love Javascript!
#2, I love Java!

  有时,我们需要对数组的元素做出一个挑选,这时可以这样干:

代码如下:

1
2
3
# 找出符合条件的值
b = [1,2,3].find_all{ |x| x % 2 == 1 }
# b的值是 [1,3]

 有时,我们需要删除数组中的某些值。这时:

代码如下:

1
2
3
4
# 迭代并根据条件刪除
a = [51101256]
a.delete_if {|x| x >= 100 }
# a的值是 [51]

再来一个例子:

代码如下:

1
2
3
4
5
6
7
# 找出最长字串find the longest word
longest = ["cat""sheep""bear"].inject do |memo,word|
    ( memo.length > word.length )? memo : word
end
puts longest
#输出如下:
#sheep


Map迭代器

  在Java中,如果相对Map使用迭代器,必须把Map转化成List类型的容器才行。但是,在Ruby中,有直接针对Map的迭代器,很好很方便:

代码如下:

1
2
3
4
5
6
sum = 0
outcome = {"book1"=>1000"book2"=>1000,"book3"=>4000}
outcome.each{|item, price|
 sum += price
}
print "Sum="+sum.to_s

甚至,我们还可以这样:

代码如下:

1
2
3
4
5
6
sum = 0
outcome = {"book1"=>1000"book2"=>1000,"book3"=>4000}
outcome.each{|pair|
 sum += pair[1# 读取值
}
print "Sum="+sum.to_s

这里说明一下:上述程序使用了pair[1]读取Map的值,如果要读取Map的键时则写成pair[0]。

如果需要输出Map的Key,可以这样:

代码如下:

1
2
3
4
outcome = {"book1"=>1000"book2"=>1000,"book3"=>4000}
outcome.each_key do |k|
 puts k
end

如果需要输出Map的value,则可以这样:

代码如下:

1
2
3
4
outcome = {"book1"=>1000"book2"=>1000,"book3"=>4000}
outcome.each_value do |v|
 puts v
end


文件迭代器

  实在是没有想到,对于文件,Ruby也有迭代器可用。如下:

代码如下:

1
2
3
4
5
f = File.open("sample.txt")
f.each{|line|
 print line
}
f.close

其实,我们可以使用代码块来进行同样的操作:

代码如下:

1
2
3
4
5
File.open("str.rb""r"do |file|
    file.each{|line|
  print line
 }
end

使用代码块,不需要手动close。这个推荐!


目录迭代器

很多时候,我们需要列出某个目录下的文件列表,设置对每个文件进行操作,这时也需要迭代器。Ruby也考虑到了:

代码如下:

1
2
3
4
Dir.foreach("c://"do |file|  # 请根据自己的系统类型,做适当的修改
 puts file
end
#输出太多,就不贴结果了。可以自己运行一下看看


结尾

  通过上面的介绍可以看出,Java和Ruby相比,在迭代器方面简直是弱爆了!当然,D瓜哥刚刚开始学习Ruby,文中有不当甚至解释错误的地方,劳烦指出,D瓜哥会尽快改正的。











本文转自 紫色葡萄 51CTO博客,原文链接:http://blog.51cto.com/purplegrape/1884400,如需转载请自行联系原作者

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
使用NAT网关轻松为单台云服务器设置多个公网IP
在应用中,有时会遇到用户询问如何使单台云服务器具备多个公网IP的问题。 具体如何操作呢,有了NAT网关这个也不是难题。
26782 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10057 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
10882 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
9156 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13871 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
11816 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
22378 0
+关注
20382
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载