アプリ版:「スタンプのみでお礼する」機能のリリースについて

初歩的な質問で申し訳ありません

ary = [Foo.new]
ary.each do |i|
 if (条件)
  ary.push(Foo.new)
 end
end

上の様にブロックの中である条件でaryに要素が追加されます。
この場合、この追加された要素はeachで漏れなく扱えるのでしょうか?
簡単なプログラムで試した限りではpushされたFooインスタンスについてもeachで取り出せているようなのですが、自信が無いので質問致します。

# coding: windows-31J

class Foo
attr_accessor :checked
attr_reader :val
RAND_MAX = 5

def initialize
rnd = Random.new
@checked = false
@val = rnd.rand(RAND_MAX).to_i
end
end

ary = [Foo.new]

ary.each do |f|
if f.val > 0
ary.push(Foo.new)
end
f.checked = true
end

cnt_true = 0
cnt_false = 0
ary.each_index do |idx|
print "#{idx} #{ary[idx].checked} #{ary[idx].val}\n"
if ary[idx].checked
cnt_true += 1
else
cnt_false += 1
end
end
puts "checked true = #{cnt_true}"
puts "checked false = #{cnt_false}"



よろしくお願いします。

A 回答 (1件)

Array#eachではイテレート毎に要素数のチェックをしてるので、後ろに足していく


pushなら問題ないみたいです。イテレート中のpopも大丈夫です。
でも、Arrayの先頭を操作する、shiftやunshiftでは内部ループカウンタとインデックスが
ずれるのでダメですね。
一応CRubyの実装をコピペしときます。

array.c:
VALUE
rb_ary_each(VALUE ary)
{
  long i;

  RETURN_ENUMERATOR(ary, 0, 0);
  for (i=0; i<RARRAY_LEN(ary); i++) { // ←イテレート毎に長さのチェック
    rb_yield(RARRAY_PTR(ary)[i]);
  }
  return ary;
}
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。
rubyのソースまでご確認いただいて恐縮です。

とりあえずpushしか使用しないので、問題ないと伺って安心しました。もしダメだったら全ての要素がチェックされたかの確認のためのループを置かないといけないかな、と思っていたのですが必要ないですね。
ちなみに試しに上のテストプログラムのpushをunshiftに書き換えてみたところ、要素が追加された場合はプログラムが無反応になりました。仰るとおりうまく行かないようです。

お礼日時:2011/09/18 19:29

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!