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 и каждый раз увеличивая индекс, пока не закончится.Но когда вы удаляете элемент, он все равно увеличивает индекс, поэтому он не оценивает один и тот же индекс дважды, как я хочу.
Это может быть не тем, что происходит, ноэто лучшее, что я могу придумать.
Есть ли чистый способ сделать это?Уже есть встроенный итератор, который может это сделать?Или мне придется испачкать его и сделать итератор индекса массива, а не увеличивать его при удалении элемента?(или перебрать клон массива и удалить из исходного массива)
Уточнение
Я не хочу просто удалять элементы измассив;извините, если это было ясно.Что я хотел бы сделать, так это перебрать каждый элемент и «обработать» его;этот процесс может иногда удалить его.Чтобы быть более точным:
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 убирает вещи, которые должны быть найдены.