1. 程式人生 > Ruby 程式語言入門 >19 Ruby 的迭代器

19 Ruby 的迭代器

迭代意味著像迴圈一樣多次執行一次事情,它一個接一個返回陣列或雜湊裡面的元素,本章中會為大家介紹 Ruby 都有哪些迭代器。

1. each

Ruby 的每個迭代器都從雜湊和陣列中返回每個元素,最常見的是 each 迭代器。

下面是一個數組的例子。

例項:

[1, 2, 3, 4, 5].each do |number|
  puts number
end

# ---- 輸出結果 ----
1
2
3
4
5

解釋:number 引數代表著每次迭代器迴圈的每個元素,一共迴圈 5 次,分別輸出 1,2,3,4,5。

上面的場景同樣適用於雜湊:

例項:

{a: 1, b: 2, c: 3}.each
do |item| puts "======" puts item puts item.class puts "======" end # ---- 輸出結果 ---- ====== a 1 Array ====== ====== b 2 Array ====== ====== c 3 Array ======

解釋:通過上述例子我們可以看到,我們在每次迭代出來的元素是一個Array,第一個元素是每個鍵值對的鍵,第二個元素是每個鍵值對的值。

1.1 each_key 和 each_value

對於雜湊,我們還可以只迭代其值或者鍵。這裡我們有2個方法,一個是each_key

,一個是each_value,它們分別迭代雜湊的所有鍵和所有值:

例項:

{a: '1', b: '2', c: '3', d: '4', e: '5'}.each_key do |key|
  puts "key:#{key}"
end

# ---- 輸出結果 ----
key:a class: Symbol
key:b class: Symbol
key:c class: Symbol
key:d class: Symbol
key:e class: Symbol

例項:

{a: '1', b: '2', c: '3', d: '4', e: '5'}.each_value do |value|
puts "value:#{value} class: #{value.class}" end # ---- 輸出結果 ---- value:1 class: String value:2 class: String value:3 class: String value:4 class: String value:5 class: String

2. each_with_index

each 的基礎上我們還需要打印出每一個元素對應的索引,這樣我們可以使用each_with_index

下面是一個數組的例子。

例項:

[1, 2, 3, 4, 5].each_with_index do |number, index|
  puts "index: #{index} \nnumber:#{number}"
end

# ---- 輸出結果 ----
index: 0 number:1
index: 1 number:2
index: 2 number:3
index: 3 number:4
index: 4 number:5

解釋:上述程式碼我們塊中增加了一個index,它代表著每個元素的索引,從0開始依次加1。

下面是一個雜湊的例子:

例項:

{a: '1', b: '2', c: '3', d: '4', e: '5'}.each_with_index do |value, index|
  puts "value:#{value} class: #{value.class} index: #{index}"
end

# ---- 輸出結果 ----
value:[:a, "1"] class: Array index: 0
value:[:b, "2"] class: Array index: 1
value:[:c, "3"] class: Array index: 2
value:[:d, "4"] class: Array index: 3
value:[:e, "5"] class: Array index: 4

3. 迭代器的返回值

上面我們講了each,在Ruby中我們類似each的迭代器還有很多,比如:mapcollectinjectrejectselect等,用到這些迭代器的時候,我們主要使用它們的返回值。

讓我們以陣列[1,2,3,4,5,6,7,8,9,10]舉例:

3.1 each

each 可以把陣列每個元素作為引數執行操作,但返回值仍是陣列本身。

例項:

a = [1,2,3,4,5,6,7,8,9,10].each {|e| puts e.to_s + '!'}
puts a.to_s

# ---- 輸出結果 ----
1!
2!
3!
4!
5!
6!
7!
8!
9!
10!
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

3.2 map

對每個陣列元素執行操作,原始陣列未修改,返回值是修改之後的陣列。

例項:

a = [1,2,3,4,5,6,7,8,9,10].map{|e| e*3 }
puts a.to_s

# ---- 輸出結果 ----
[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]

3.3 collect

collectmap的別名方法,用法同map

3.4 inject

取一個累加器(sum)並更改它的值為與陣列中的元素一樣多的次數。返回累加器的最終值。

例項:

a = [1,2,3,4,5,6,7,8,9,10].inject{|sum,e| sum += e }
puts a

# ---- 輸出結果 ----
55

3.5 reduce

reduceinject的別名,使用方法一樣,不過更多用於遞減操作。

3.6 select

為每個陣列元素執行一個表示式,如果為true,則將該元素新增到返回的輸出中。在其他語言中,這稱為過濾器。

例項:

a = [1,2,3,4,5,6,7,8,9,10].select{|el| el%2 == 0 }
puts a.to_s

# ---- 輸出結果 ----
[2,4,6,8,10]

3.7 find

取得一個表示式並返回該表示式返回true的第一個元素:

例項:

a = [1,2,3,4,5,6,7,8,9,10].find{|el| el / 2 == 2 }
puts a.to_s

# ---- 輸出結果 ----
4

3.8 detect

find的別名,用法和它相同。

3.9 reject

select的相反方法:為每個陣列元素執行一個表示式,如果表示式為false,則在輸出中包含該元素。

例項:

a = [1,2,3,4,5,6,7,8,9,10].reject{|e| e==2 || e==8 }
puts a.to_s

# ---- 輸出結果 ----
[1, 3, 4, 5, 6, 7, 9, 10]

4. 次數迭代器

有的時候我們需要進行固定迭代次數的操作,這個時候我們通常有3種方式,使用範圍(Range)、使用times方法,使用upto或者downto方法。

4.1 範圍迭代

使用範圍來固定迭代次數:

例項:

(1..5).each do |i|   
   puts i   
end   

# ---- 輸出結果 ----
1
2
3
4
5

解釋:因為 1..5 代表的是從 1~5 的所有數字,所以可以遍歷 5 次。

在進行範圍迭代的時候,我們可以使用step來選擇每次迭代的步長。

例項:

(0..50).step(5) do |n|
  puts n
end

# ---- 輸出結果 ----
0
5
10
15
20
25
30
35
40
45
50

解釋:我們正常使用範圍迭代的時候,都是每次遞增1的,而使用step,我們可以選擇每次迭代一次遞增5個。

4.2 times 迭代

times我們在英文中翻譯成次數,Ruby的Integer有一個很通俗易懂的例項方法名字就叫times,可以讓我們迴圈固定次數。

例項:

5.times.each do |i|
  puts i
end

# ---- 輸出結果 ----
0
1
2
3
4

解釋:這裡 5 呼叫了它的times方法,它可以簡單理解成為建立了一個從 0~4 的陣列。

例項:

5.times.to_a

# ---- 輸出結果 ----
[0, 1, 2, 3, 4]

4.3 upto 和 downto 迭代

這兩個同樣也是 Integer 類的例項方法。

例項:

1.upto(5) do |n|   
  puts n   
end  

# ---- 輸出結果 ----
1
2
3
4
5

解釋:通俗的解釋,從1一直迭代到5,和[1, 2, 3, 4 ,5]陣列同理。

例項:

1.upto(5).to_a

# ---- 輸出結果 ----
[1, 2, 3, 4, 5]

上述是一種遞增迭代的形式,另外一種是遞減的形式。

例項:

5.downto(1) do |n|
  puts n
end

# ---- 輸出結果 ----
5
4
3
2
1

**解釋:**會從5一直迭代到1,和 [5, 4, 3, 2, 1] 同理。

例項:

5.upto(1).to_a

# ---- 輸出結果 ----
[5, 4, 3, 2, 1]

5. 小結

本小節中,我們瞭解了迭代類似於迴圈,學習了each迭代器,each_with_index迭代器,瞭解了各種迭代器的返回值,以及三種固定次數的迭代器:範圍迭代、times迭代,uptodownto迭代。