【Ruby on Rails全棧課程】2.7 塊(Block)和迭代器

weixin_34124651發表於2018-12-15

1、塊(Block)

塊是ruby 的一個獨特特性,是一種可以和方法呼叫相關聯的程式碼塊。
是在花括號{}或者do…end之間的一組程式碼,一般我們在單行中block用花括號{},在多行中用do…end

(1)塊的格式
物件.方法名(引數列表)|塊變數| 
塊程式碼 
end
物件.方法名(引數列表){|塊變數| 塊程式碼 }
(2)塊的用法

塊(block)與方法關聯之後,在關聯的方法中用yield語句,呼叫相關聯的block

#定義一個名為block_test的方法
irb(main):001:0> def block_test
#yield代表塊裡面的內容
irb(main):002:1> yield
irb(main):003:1> yield
irb(main):004:1> yield
irb(main):005:1> end
=> :block_test
#block_test方法後面跟著塊{ puts "Hi" },將塊關聯到了方法上,方法中每個yield語句都會呼叫一次塊
irb(main):006:0> block_test { puts "Hi" }
Hi
Hi
Hi

在實際的專案中,塊通常與迭代器結合使用,這樣會使程式碼很簡練,下面我們來介紹一下迭代器以及與塊的結合使用。

2、迭代器(Enumerator)

迭代器具有遍歷容器型資料結構(陣列、雜湊等)的能力,每一種容器型資料結構(陣列、雜湊等)都有自己的迭代器。通過塊可以很簡單的操作迭代器

(1)each,連續訪問集合的所有元素,通常在遍歷資料時使用
#陣列後面跟著each,就是一個迭代器物件,下面返回了陣列的each迭代器物件
irb(main):007:0> [1,2,3,4,5].each
=> #<Enumerator: [1, 2, 3, 4, 5]:each>
#在塊中(即大括號{}中的程式碼),兩條豎線|i|之間的i代表遍歷陣列返回的每個陣列元素
#puts i將資料每個元素按照順序列印出來
irb(main):008:0> [1,2,3,4,5].each {|i| puts i }
1
2
3
4
5
(2)map、collect,從集合中獲得各個元素傳遞給塊(block),塊中程式碼返回的結果生成新的集合。如果需要將集合中的每個元素做操作返回到一個新陣列中,通常使用map。比如將集合中的元素統一換成大寫、統一將字串轉換成陣列。

map和collect相同的用法。

#將陣列的元素統一換成大寫
irb(main):023:0> ["a","b","c"].map{|i| i.upcase}
=> ["A", "B", "C"]
#統一將陣列中的元素由字串轉換成陣列。
irb(main):002:0> ["101","102","103"].map{|x| x.to_i}
=> [101, 102, 103]
#這種寫法等同於上面的寫法,專案中我們一般都是這樣寫。需要注意的是,這裡用的是小括號()而不是大括號{}
irb(main):003:0> ["101","102","103"].map(&:to_i)
=> [101, 102, 103]
(3)select,從集合中獲得各個元素傳遞給塊(block),返回陣列中所有滿足block條件的值,生成新的集合。
irb(main):014:0> [1,2,3,4,5].select{|i| i>3}
=> [4, 5]
(4)reject,從集合中獲得各個元素傳遞給塊(block),返回陣列中所有不滿足block條件的值,生成新的集合。
irb(main):099:0> [1,2,3,4,5].reject{|i| i>3}
=> [1, 2, 3]
(5)inject,遍歷整個集合中的各個元素,將各個元素,按照一定的方式累積,最後返回一個新的元素。
#inject後面跟的塊有兩個引數,第一次遍歷時,第一個引數是陣列第一個值,第二個引數是陣列第二個值
#之後遍歷,塊中程式碼計算的值傳給sum,而per是陣列中元素的遍歷
irb(main):016:0> [1,2,3,4,5].inject {|sum,per| sum+per}
=> 15
#讓我們更加直觀的看一下
irb(main):015:0> [1,2,3,4,5].inject {|sum,per| puts "sum:#{sum},per:#{per}";sum+per}
sum:1,per:2
sum:3,per:3
sum:6,per:4
sum:10,per:5
=> 15
#當inject後面指定了引數,第一個sum就是指定的這個引數  ,而per也是陣列的第一個值
irb(main):017:0> [1,2,3,4,5].inject(7) {|sum,per| puts "sum:#{sum},per:#{per}";sum+per}
sum:7,per:1
sum:8,per:2
sum:10,per:3
sum:13,per:4
sum:17,per:5
=> 22

相關文章