379

PHP は、さまざまな問題を抱えていますが、この点ではかなり優れています。配列とハッシュの間に違いはありません(私は単純かもしれませんが、これは明らかに私には正しいようです)。

foreach (array/hash as $key => $value)

Ruby では、この種のことを行う方法がたくさんあります。

array.length.times do |i|
end

array.each

array.each_index

for i in array

私はいつも使用しているので、ハッシュはより理にかなっています

hash.each do |key, value|

配列に対してこれを行うことができないのはなぜですか? メソッドを 1 つだけ覚えたい場合はeach_index(インデックスと値の両方が使用可能になるため) 使用できると思いarray[index]ますが、 value.


そうそう、私は忘れていましarray.each_with_indexた。しかし、これは行ったり来たりするので最悪|value, key|です!これは非常識ではありませんか?hash.each|key, value|

4

12 に答える 12

606

これは、すべての要素を反復処理します。

array = [1, 2, 3, 4, 5, 6]
array.each { |x| puts x }

# Output:

1
2
3
4
5
6

これは、値とインデックスを提供するすべての要素を反復処理します。

array = ["A", "B", "C"]
array.each_with_index {|val, index| puts "#{val} => #{index}" }

# Output:

A => 0
B => 1
C => 2

あなたの質問から、あなたが探しているものはよくわかりません。

于 2008-11-22T00:40:50.550 に答える
101

正解は一つではないと思います。繰り返しにはさまざまな方法があり、それぞれに独自のニッチがあります。

  • each私はインデックスをあまり気にしないので、多くの用途には十分です。
  • each_ with _indexHash#each のように動作します - 値とインデックスを取得します。
  • each_index- インデックスのみ。私はこれを頻繁に使用しません。「length.times」と同等。
  • mapは反復する別の方法で、ある配列を別の配列に変換する場合に便利です。
  • selectサブセットを選択するときに使用する反復子です。
  • inject合計や積を生成したり、単一の結果を収集したりするのに役立ちます。

覚えるのが大変に思えるかもしれませんが、すべてを知らなくても大丈夫です。しかし、さまざまな方法を学び、使用し始めると、コードはよりクリーンで明確になり、Ruby の習得への道を歩むことになります。

于 2008-11-22T00:58:50.530 に答える
61

Array->|value,index|Hash->が正気ではないと言っているので|key,value|はありませんが(Horace Loebのコメントを参照)、この取り決めを期待する正気の方法があると言っています。

配列を扱うときは、配列内の要素に焦点を合わせます(インデックスは一時的なものであるため、インデックスではありません)。メソッドはそれぞれインデックス付きです。つまり、each + index、または| each、index |、または|value,index|。これは、インデックスがオプションの引数として表示されていることとも一致しています(例:| value |)。| value、index =nil|と同等です これは|value、index|と一致しています。

ハッシュを処理するときは、値よりもキーに重点を置くことが多く、通常はキーと値をまたはのいずれかの順序で処理しkey => valueますhash[key] = value

ダックタイピングが必要な場合は、Brent Longboroughが示したように定義されたメソッドを明示的に使用するか、maxhawkinsが示したように暗黙的なメソッドを使用します。

Rubyは、プログラマーが言語に合わせて調整することではなく、プログラマーに合わせて言語を調整することを目的としています。これが非常に多くの方法がある理由です。何かについて考える方法はたくさんあります。Rubyでは、最も近いものを選択すると、コードの残りの部分は通常、非常にきれいかつ簡潔になります。

「Rubyで配列を反復処理する「正しい」方法は何ですか?」という元の質問については、コアな方法(つまり、強力な構文糖衣構文やオブジェクト指向の力がない場合)は次のことを行うことだと思います。

for index in 0 ... array.size
  puts "array[#{index}] = #{array[index].inspect}"
end

しかし、Rubyはすべて強力なシンタックスシュガーとオブジェクト指向のパワーに関するものですが、とにかくここではハッシュと同等であり、キーを注文することも注文しないこともできます。

for key in hash.keys.sort
  puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end

したがって、私の答えは、「Rubyで配列を反復処理する「正しい」方法は、ユーザー(つまり、プログラマーまたはプログラミングチーム)とプロジェクトによって異なります。」です。より優れたRubyプログラマーは、より優れた選択を行います(どの構文能力および/またはどのオブジェクト指向アプローチか)。優れたRubyプログラマーは、さらに多くの方法を探し続けています。


ここで、別の質問をしたいと思います。「Rubyの範囲を逆方向に反復する「正しい」方法は何ですか?」(この質問は、私がこのページにたどり着いた方法です。)

(フォワードのために)行うのはいいことです:

(1..10).each{|i| puts "i=#{i}" }

しかし、私は(後方のために)するのが好きではありません:

(1..10).to_a.reverse.each{|i| puts "i=#{i}" }

ええと、私は実際にはそれをやりすぎてもかまいませんが、逆方向に教えるときは、生徒に良い対称性を示したいと思います(つまり、最小の違いで、たとえば逆を追加するか、ステップ-1を追加するだけですが、他のものを変更する)。あなたができること(対称性のために):

(a=*1..10).each{|i| puts "i=#{i}" }

(a=*1..10).reverse.each{|i| puts "i=#{i}" }

あまり好きではありませんが、できません

(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" }   # I don't want this though.  It's dangerous

あなたは最終的にすることができます

class Range

  def each_reverse(&block)
    self.to_a.reverse.each(&block)
  end

end

しかし、私はオブジェクト指向のアプローチではなく、純粋なRubyを教えたいと思っています(まだ)。逆方向に繰り返したい:

  • 配列を作成せずに(0..1000000000を考慮)
  • 任意の範囲で機能します(整数だけでなく文字列など)
  • 余分なオブジェクト指向の力を使用せずに(つまり、クラスの変更なし)

これは、メソッドを定義しないと不可能だと思いますpred。つまり、それを使用するようにRangeクラスを変更する必要があります。これができる場合はお知らせください。そうでない場合は、残念ながら不可能の確認をお願いします。おそらくRuby1.9はこれに対処しています。

(これを読んでくれてありがとう。)

于 2009-03-27T23:25:21.510 に答える
20

両方が必要な場合は、each_with_index を使用します。

ary.each_with_index { |val, idx| # ...
于 2008-11-22T00:44:06.767 に答える
12

他の答えは問題ありませんが、もう 1 つ周辺的なことを指摘したいと思います。配列は順序付けられていますが、ハッシュは 1.8 ではありません。(Ruby 1.9 では、ハッシュはキーの挿入順で並べられます。) したがって、1.9 より前では、配列と同じ方法/シーケンスでハッシュを反復処理することは意味がありませんでした。配列には常に明確な順序がありました。PHP 連想配列のデフォルトの順序はわかりません (明らかに、私の Google fu もそれを理解できるほど強力ではありません)。連想配列の順序は定義されていないように見えるため、このコンテキストでは「同じ」である必要があります。

そのため、Ruby の方法はより明確で直感的に思えます。:)

于 2008-11-23T16:19:33.430 に答える
11

以下は、あなたの質問に記載されている 4 つのオプションであり、制御の自由によって配置されています。必要なものに応じて、別のものを使用することをお勧めします。

  1. 単純に値を調べます:

    array.each
    
  2. インデックスを通過するだけです:

    array.each_index
    
  3. インデックス + インデックス変数を通過します。

    for i in array
    
  4. 制御ループ回数 + インデックス変数:

    array.length.times do | i |
    
于 2015-08-21T17:07:08.447 に答える
9

配列とハッシュで同じことを一貫して行おうとするのはコードの匂いかもしれませんが、一貫した動作を探しているのであれば、私がコードの匂いがするかもしれません。 ?:

class Hash
    def each_pairwise
        self.each { | x, y |
            yield [x, y]
        }
    end
end

class Array
    def each_pairwise
        self.each_with_index { | x, y |
            yield [y, x]
        }
    end
end

["a","b","c"].each_pairwise { |x,y|
    puts "#{x} => #{y}"
}

{"a" => "Aardvark","b" => "Bogle","c" => "Catastrophe"}.each_pairwise { |x,y|
    puts "#{x} => #{y}"
}
于 2008-11-22T13:57:01.770 に答える
5

ハッシュを使用して( CampingおよびMarkabyで)メニューを作成しようとしていました。

各項目にはメニュー ラベルURLの 2 つの要素があるため、ハッシュは正しいように見えましたが、「ホーム」の「/」URL は常に最後に表示されたため (ハッシュに期待されるように)、メニュー項目が間違って表示されました。注文。

配列を使用すると、each_slice次のようになります。

['Home', '/', 'Page two', 'two', 'Test', 'test'].each_slice(2) do|label,link|
   li {a label, :href => link}
end

各メニュー項目に追加の値 (CSS ID名など) を追加することは、単にスライス値を増やすことを意味します。つまり、ハッシュに似ていますが、任意の数のアイテムで構成されるグループがあります。完全。

これは、うっかりして解決策をほのめかしてくれたことに感謝するためです。

明白ですが、言及する価値があります。配列の長さがスライス値で割り切れるかどうかを確認することをお勧めします。

于 2009-06-15T10:41:44.437 に答える
4

(Rails のように)列挙可能なmixinを使用すると、リストされている php スニペットと同様のことができます。each_slice メソッドを使用してハッシュを平坦化するだけです。

require 'enumerator' 

['a',1,'b',2].to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

# is equivalent to...

{'a'=>1,'b'=>2}.to_a.flatten.each_slice(2) {|x,y| puts "#{x} => #{y}" }

モンキー パッチの必要性が少なくなります。

ただし、再帰配列または配列値を持つハッシュがある場合、これは問題を引き起こします。Ruby 1.9 では、再帰の深さを指定する flatten メソッドへのパラメーターを使用して、この問題を解決しています。

# Ruby 1.8
[1,2,[1,2,3]].flatten
=> [1,2,1,2,3]

# Ruby 1.9
[1,2,[1,2,3]].flatten(0)
=> [1,2,[1,2,3]]

これがコードの匂いなのかという質問については、よくわかりません。通常、何かを反復するために後ろに曲がらなければならないときは、一歩下がって、問題への取り組みが間違っていることに気づきます。

于 2009-01-13T05:16:25.440 に答える