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>
この列挙子の最初の要素が生成されてブロックに渡され、3 つのブロック変数に値が割り当てられます。
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"]
の 2 番目と最後の要素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"
印刷されます。
の 2 番目と最後の要素がenum0
生成され、ブロックに渡され、3 つのブロック変数に値が割り当てられます。
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
ステートメントの必要がなくなります。これら 2 つのステートメントの機能は、もちろん using の行にありますが、ほとんどの Ruby ユーザーは、 にチェーンするときの流れを好みます。もう 1 つの違いは、 の値がのブロックに限定されることです。これは、優れたプログラミング手法です。arr = [a+b]
puts arr.join(' ')
each_with_object
each_with_object
join(' ')
arr
each_with_object