Mix-in Enumerator得到的迭代方法:數組
each_cons(n) { ... } → nil each_cons(n) → an_enumerator
迭代容器中的每一個元素,都從其開始向後取連續n個元素組成一個數組傳遞到語句塊中。ruby
(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(n) { ... } → nil each_slice(n) → an_enumerator
每次從容器中取出n個元素組成數組傳遞到語句塊中。code
(1..10).each_slice(3) { |a| p a } ## 輸出: =begin [1, 2, 3] [4, 5, 6] [7, 8, 9] [10] =end
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}
e.with_index(offset = 0) {|(*args), idx| ... } e.with_index(offset = 0)
迭代容器每一個元素,將元素和對應的index傳遞給語句塊中的兩個變量。能夠指定參數offset,使得傳遞給語句塊的index變量從offset開始(即傳遞每一個原始index加上offset後的值)。默認,offset=0,等價於each_with_index。blog
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(obj) { |(*args), memo_obj| ... } → obj each_with_object(obj) → an_enumerator
實現相似於reject/reduce的功能。迭代每一個元素,而後將元素傳遞給語句塊中的變量,於此同時,還會指定一個obj參數對象做爲memo_obj變量的初始值,最後通過語句塊的操做以後,返回obj最初引用的對象。字符串
必須注意,obj應該傳遞可變對象,並保證在語句塊中沒有改變obj對象的引用,不然each_with_object將老是返回初始值。見下面示例分析。hash
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。it
再好比下面的例子中,傳遞初始字符串對象"x",兩個語句塊都將每次迭代的字母追加到這個字符串對象的尾部,可是結果卻不一樣。class
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
傳遞容器中每一個元素給語句塊,並從語句塊中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