Ruby中的迭代器詳解

来源:互联网 发布:mac 配置ant 编辑:程序博客网 时间:2024/03/29 04:50

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中就有。下面,我們通過代碼來演示一下:

str = "abc"str.each_byte {|c| printf ">%c", c};  ## 輸出如下:(為了和代碼區別,D瓜哥在輸出前面人為地加了#。)# 以下的輸出展示,處理方式相同。#>a>b>c

each_byte 是字串中用於處理每個位元組的迭代器。每個位元組都會代入塊參數 c 中。


Ruby中,不僅有用於位元組的迭代器,還有用於每行的迭代器。示例如下:



str = "abc\nefg\nhijk"str.each_line{|l| print l}# 輸出如下:#abc#efg#hijk

怎麼樣,是不是被Ruby簡練但強大的迭代器所折服?!好戲還在後面,接著向下看。


數字迭代器


  在Ruby中,「一切皆為對象」,甚至數字也是對象。這點和Java不一樣。所以,對字的迭代器,對於我這個Java程序猿也是聞所未聞。讓我們寫兩個示例,管窺一二。


  第一個場景:對某段代碼進行N(比如5)次操作。在Java中,需要寫個循環,但是在Ruby中,只需要調用一下times方法即可。代碼如下:

5.times {print "I love / \n"} # 真的就這麼簡單# 輸出如下:#I love /#I love /#I love /#I love /#I love /

第二個場景:求1到5的數字之和。這個也特別簡單:

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

如果使用upto函數,還可以這樣寫:

sum = 01.upto(5) {|x| sum += x }print "Sum="+sum.to_s

 有時,我們的步進不一定是1,可能是2,例如奇數和。這種情況下,可以使用step函數。代碼如下:

sum = 0   1.step(5, 2) do |y| # step函數第二個參數是步進。sum += y   end  print "Sum="+sum.to_s

感覺有點扯遠了。下面,我們講講數組相關的迭代器。


數組迭代器


見識過了數字相關的迭代器,我們再看看數組相關的迭代器。


第一個場景:便利數組並輸出每個元素。直接上代碼:

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!

  有時,我們需要對數組的元素做出一個挑選,這時可以這樣干:

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

 有時,我們需要刪除數組中的某些值。這時:

# 迭代並根據條件刪除a = [51, 101, 256]a.delete_if {|x| x >= 100 }# a的值是 [51]

再來一個例子:



# 找出最長字串find the longest wordlongest = ["cat", "sheep", "bear"].inject do |memo,word|( memo.length > word.length )? memo : wordendputs longest#輸出如下:#sheep

Map迭代器


  在Java中,如果相對Map使用迭代器,必須把Map轉化成List類型的容器才行。但是,在Ruby中,有直接針對Map的迭代器,很好很方便:



sum = 0outcome = {"book1"=>1000, "book2"=>1000,"book3"=>4000}outcome.each{|item, price|sum += price}print "Sum="+sum.to_s

甚至,我們還可以這樣:

sum = 0outcome = {"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,可以這樣:

outcome = {"book1"=>1000, "book2"=>1000,"book3"=>4000}outcome.each_key do |k|puts kend

如果需要輸出Map的value,則可以這樣:



outcome = {"book1"=>1000, "book2"=>1000,"book3"=>4000}outcome.each_value do |v|puts vend

文件迭代器


  實在是沒有想到,對於文件,Ruby也有迭代器可用。如下:

f = File.open("sample.txt")f.each{|line|print line}f.close

其實,我們可以使用代碼塊來進行同樣的操作:



File.open("str.rb", "r") do |file|file.each{|line|print line}end

使用代碼塊,不需要手動close。這個推薦!


目錄迭代器


很多時候,我們需要列出某個目錄下的文件列表,設置對每個文件進行操作,這時也需要迭代器。Ruby也考慮到了:

Dir.foreach("c://") do |file|  # 請根據自己的系統類型,做適當的修改puts fileend#輸出太多,就不貼結果了。可以自己運行一下看看

結尾


  通過上面的介紹可以看出,Java和Ruby相比,在迭代器方面簡直是弱爆了!當然,D瓜哥剛剛開始學習Ruby,文中有不當甚至解釋錯誤的地方,勞煩指出,D瓜哥會儘快改正的。

0 0
原创粉丝点击