letters.each do |a,b,*rest|
puts rest.each_with_object([a+b]) { |s,arr| arr << arr.first + s }.join(' ')
end
印刷
AB
CD CDF CDG
HI HIJ
步骤如下。
认为
letters = [["C", "D", "F", "G"],["H", "I", "J" ]]
然后
enum0 = letters.each
#=> #<Enumerator: [["C", "D", "F", "G"], ["H", "I", "J"]]:each>
生成此枚举器的第一个元素并将其传递给块,并为三个块变量赋值。
a, b, *rest = enum0.next
#=> ["C", "D", "F", "G"]
a
#=> "C"
b
#=> "D"
rest
#=> ["F", "G"]
接下来,我们得到
enum1 = rest.each_with_object([a+b])
#=> rest.each_with_object(["CD"])
#=> #<Enumerator: ["F", "G"]:each_with_object(["CD"])>
生成此枚举器的第一个元素并将其传递给块,并为块变量赋值。
s, arr = enum1.next
#=> ["F", ["CD"]]
s
#=> "F"
arr
#=> ["CD"]
现在执行块计算。
arr << arr.first + s
#=> arr << "CD" + "F"
#=> ["CD", "CDF"]
的第二个和最后一个元素enum1
被生成并传递给块,块变量被赋值并计算块。
s, arr = enum1.next
#=> ["G", ["CD", "CDF"]]
arr << arr.first + s
#=> ["CD", "CDF", "CDG"]
当尝试从enum1
我们获得另一个元素时
enum1.next
#StopIteration: iteration reached an end
Ruby 通过跳出块并返回来处理异常arr
。arr
然后加入的元素:
arr.join(' ')
#=> "CD CDF CDG"
并打印。
现在生成的第二个也是最后一个元素enum0
,传递给块,三个块变量被赋值。
a, b, *rest = enum0.next
#=> ["H", "I", "J"]
a
#=> "H"
b
#=> "I"
rest
#=> ["J"]
其余计算类似。
有的读者可能对Enumerable#each_with_object这个方法不熟悉,这个方法被广泛使用。阅读文档,但请注意,这里它产生的结果与如下编写的代码相同。
letters.each do |a,b,*rest|
arr = [a+b]
rest.each { |s| arr << arr.first + s }
puts arr.join(' ')
end
通过使用each_with_object
我们避免了对语句arr = [a+b]
和语句的需要puts arr.join(' ')
。这两个语句的功能当然在 using 行中,但是大多数 Ruby 用户在链接到each_with_object
时更喜欢流。另一个区别是 ' 的值仅限于' 块,这是良好的编程习惯。 each_with_object
join(' ')
arr
each_with_object