k = [1,2,3,4,5]
for n in k
puts n
if n == 2
k.delete(n)
end
end
puts k.join(",")
# Result:
# 1
# 2
# 4
# 5
# [1,3,4,5]
# Desired:
# 1
# 2
# 3
# 4
# 5
# [1,3,4,5]
これと同じ効果が、他の配列反復子 k.each でも発生します。
k = [1,2,3,4,5]
k.each do |n|
puts n
if n == 2
k.delete(n)
end
end
puts k.join(",")
同じ出力があります。
これが起こっている理由は非常に明確です...Rubyは配列に格納されたオブジェクトを実際に反復処理するのではなく、インデックス0から開始し、終了するまで毎回インデックスを増やして、きれいな配列インデックスイテレータに変換します。 . ただし、アイテムを削除してもインデックスはインクリメントされるため、同じインデックスを 2 回評価することはありません。
これは起こっていることではないかもしれませんが、私が考えることができる最高のものです.
これを行うためのきれいな方法はありますか?これを実行できる組み込みイテレータは既にありますか? それとも、アイテムが削除されたときにインクリメントせずに、それを汚して配列インデックス イテレータを実行する必要がありますか? (または、配列のクローンを反復処理し、元の配列から削除します)
明確化
単に配列から項目を削除したいだけではありません。それが明らかだったらごめんなさい。私がやりたいことは、各要素を繰り返し処理し、それを「処理」することです。このプロセスは時々それを削除するかもしれません。より正確に言うと:
class Living_Thing
def initialize tracker,id
@tracker = tracker
@id = id
@tracker << self
end
def process
do_stuff
puts @id
if @id == 2
die
end
end
def die
do_stuff_to_die
@tracker.delete(self)
end
def inspect
@id
end
end
tracking_array = Array.new()
foo = Living_Thing.new(tracking_array,1)
bar = Living_Thing.new(tracking_array,2)
rab = Living_Thing.new(tracking_array,3)
oof = Living_Thing.new(tracking_array,4)
puts tracking_array.join(",") # => [1, 2, 3, 4]
for n in tracking_array
n.process
end
# result: only foo, bar, and oof are processed
理想的には、tracking_array 内のすべてのアイテムを処理したいと思います。
Living_Thing が tracking_array から削除されたら、Living_Thing#die を呼び出す必要があります。do_stuff_to_die は、クラン化する必要があるものをクリーンアップします。