4

ですから、それほど難しくないことを複雑にしすぎているのかもしれませんが、これで終わりです。

Ruby には、.each というループのメソッドがあります。これは非常にクールだと思いますが、あまりクールではないと思うのは、その後に続くパイプ (または Ruby の他の do-type ループのようです) について書かれた量です。時々、パイプには単一のものがあります:

basket.each do |fruit|
    puts "This is a #{fruit}.\n"
end

ただし、このパイプには、次のように 2 つのものが含まれることがあります。

contacts.each do |name, profession|
    puts "#{name} is a #{profession}.\n"
end

私が今疑問に思っているのは、そのパイプに 3 つ以上のアイテムを入れることは可能ですか? 巨大で大きくて醜い多次元配列がある場合のように?

パイプに追加したものがない場合はどうすればよいですか? パイプの値はゼロになりますか?それともエラーになりますか?

繰り返しになりますが、これが長年の Rubyist にとって明らかである場合は申し訳ありませんが、私は厳密に型指定された変数の世界から来ました。また、PHP の世界も去ります。:)

編集

では、次のようなものがある場合はどうでしょうか。

categories = [["Bathroom", "Bathroom Fixtures", "Plumbing"],
                      ["Ceiling Fixtures", "Chandeliers", "Flush Mounts", "Mini Chandeliers", "Semi-Flush Mounts", "Pendants", "Track Lighting", "Mini Pendants", "Directional", "Island/Pool Table", "Recessed Lighting"],
                      ["Outdoor", "Exterior", "Landscape Lighting"],
                      ["Fans", "Fans", "Fan Accessories"],
                      ["Lamps", "Lamps", "Shades"],
                      ["Wall Fixtures", "Sconces", "Foyer/Hall Lanterns"],
                      ["Specialty", "Undercabinet", "Light Bulbs", "Lighting Controls", "Glass", "Specialty Items", "Utility"],
                      ["Home Decor", "Decor/Home Accents", "Furniture"]]

このようにループできますか?

categories.each do |category, subcats|
    puts "The main category is #{category} and the sub categories are: "
    subcats.each do |subcat|
        puts "#{subcat}, "
    end
end
4

4 に答える 4

5

メソッドの内訳から始めましょうeach

a = [1,2,3,4,5]

a.each do |num|
  puts num
end

# 1
# 2
# 3
# 4
# 5

そのdo ... end部分をaと呼びますblock

このブロックは、1 つのパラメーター (配列内の要素) を受け入れます。

|パラメータをブロックに渡す方法は

ブロックに複数の引数を指定する場合:

a.each do |num, x|
  puts num
  puts x
end

# 1
# 
# 2
# 
# 3
# 
# 4
# 
# 5 
# 

xnil反復ごとです。

ブロックがどのように機能するかを確認できるように、ブロックを使用する独自のメソッドを作成してみましょう。

def my_each(a=[])
  a.each do |x|
    yield x if block_given?
  end
end

my_each(a) do |num|
  puts num
end

ここでyield xは、提供されたブロックを実行しxてそれに渡します。

に別のパラメータを渡すとblock、それはnil. なんで?

の実装はmy_each、2 番目のパラメーターについて何も知らないため、yield何もしないため、残りnilます。

于 2012-07-06T17:14:53.963 に答える
4

単純な配列がある場合、次のことが起こります。

arr = [1,2,3,4]

arr.each do |x|
  p x
end
1
2
3
4
=> [1,2,3,4]

arr.each do |x,y|
  p x
  p y
end
1
nil
2
nil
3
nil
4
nil
=> [1,2,3,4]

したがって、rubyがブロック引数に何を入れるべきかわからない場合は、単にそれをに設定しnilます。次に、ネストされた配列について考えます。

arr = [[1,2],[3,4],[5,6]]

arr.each do |x|
  p x
end
[1, 2]
[3, 4]
[5, 6]
=> [[1,2],[3,4],[5,6]]

arr.each do |x,y|
  p x
  p y
end
1
2
3
4
5
6
=> [[1,2],[3,4],[5,6]]

xこの場合、rubyは、内部配列の2つの要素をブロック変数とに割り当てたいと想定していますy。同じことがハッシュにも当てはまり、Rubyはキーと値をxとに割り当てyます。

hash = {1 => 2, 3 => 4, 5 => 6}

hash.each do |x,y|
  p x
  p y
end
1
2
3
4
5
6
=> {1=>2,3=>4,5=>6}

ネストされた配列に十分な要素がない場合nil、実際にブロック変数が割り当てられます。それらが多すぎる場合、それらは単に破棄されます。

arr = [[1,2,3],[4,5],[6]]

arr.each do |x,y|
  p x
  p y
end
1
2
4
5
6
nil
=> [[1,2,3],[4,5],[6]]

かなり簡単です!

編集

編集した質問については、いいえ、この1:1をRubyコードに適用することはできません。手動で、splat演算子(*)をに適用する必要がありますsubcats。このようにして、rubyは残りのすべての要素を「splatted」ブロック変数に割り当てます。

categories.each do |category,*subcats|
    puts "The main category is #{category} and the sub categories are: "
    subcats.each do |subcat|
        puts "#{subcat}, "
    end
end

ただし、次のようなサブカテゴリのコンマ区切りリストを生成します。

categories.each do |category,*subcats|
    puts "The main category is #{category} and the sub categories are: "
    puts subcats.join(', ')
end

編集2

ああ、そしてあなたはその要素のためにたくさんのブロックパラメータを定義することによって巨大な醜い邪悪な多次元配列を扱うことはないでしょう。含まれている要素の数がわからないという理由だけで、他のほとんどすべての言語と同じように、ネストされたループを使用して反復する可能性があります。

于 2012-07-06T17:21:16.310 に答える
1

あなたが話しているパイプは、ブロック「変数」のパラメーターリストです。実際には、これはある種の関数ポインターであり、パイプはパラメーター リストをマークします。

array.eachの説明を確認してください。

これは魔法ではありません。パラメータの数はブロックで定義されています。それ以上追加することはできません。追加した場合、値は取得されません。その理由は、「いつか」複数存在する可能性があるためです。おそらく、キーと値の2つのパラメーターを持つhash.eachであるためです。

ブロック パラメーターを使用して独自の関数を作成できます。このを参照してください。

反復の問題については、ハッシュを使用するか、独自の反復子を作成できます。

于 2012-07-06T17:12:08.373 に答える
1

ブロックへの複数の引数

Array#eachは配列オブジェクトを繰り返し処理し、単一のオブジェクトをブロックに渡すか、列挙子を返します。この動作を再定義することはできますが、一度に複数の値が必要な場合、#each は間違った方法です。別の方法については、 Enumerator#each_sliceを参照してください。

データ構造

適切なデータ構造を使用すると、問題を簡単に解決できます。配列の代わりに、ハッシュの使用を検討する必要があります。例えば:

categories = 
  {"Bathroom"=>["Bathroom Fixtures", "Plumbing"],
   "Ceiling Fixtures"=>["Chandeliers", "Flush Mounts", "Mini Chandeliers"]}

categories.each do |key, value|
  puts "#{key}:"
  value.each { |v| puts "\t%s" % v }
end

これは以下を返します:

Bathroom:
    Bathroom Fixtures
    Plumbing
Ceiling Fixtures:
    Chandeliers
    Flush Mounts
    Mini Chandeliers
于 2012-07-06T19:13:44.640 に答える