0

多分誰かがこれで私を助けることができます。私は配列の配列を持っています。内部配列にはさまざまなサイズがあります (2 ~ 4 要素)。

letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]] 

各配列が最初の列の要素 [0] と要素 [1] を結合し、2 番目の列の要素 [0]、要素 [1]、要素 [2] を 3 番目の列の要素 [ 0]、要素[1]、要素[3]が結合されました。要素 2 と 3 は常に存在するとは限りません。

私が得ようとしている出力は次のようなものです:

AB
CD CDF CDG
HI HIJ

私はこのようにやっていますが、このエラーが発生しています。

letters.map{|x| puts x[0]+x[1] + "," + x[0]+x[1]+x[2] + "," + x[0]+x[1]+x[3]}
TypeError: no implicit conversion of nil into String
        from (irb):1915:in "+"
        from (irb):1915:in "block in irb_binding"
        from (irb):1915:in "map"
        from (irb):1915
        from /usr/bin/irb:11:in "<main>"
4

3 に答える 3

2
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_objectjoin(' ')arreach_with_object

于 2018-05-19T02:38:59.327 に答える
1

好奇心から、唯一のEnumerable#map解決策です。

letters = [["A", "B"],["C", "D", "F", "G"],["H", "I", "J" ]]

letters.map do |f, s, *rest|
  rest.unshift(nil).map { |l| [f, s, l].join }.join(' ')
end.each(&method(:puts))

#⇒ AB
#  CD CDF CDG
#  HI HIJ
于 2018-05-19T04:19:54.390 に答える