我有这个:
puts pids
pids.each do |pid|
puts "Running on pid #{pid}"
begin
Process::kill(0, pid)
puts "Pid #{pid} still alive"
rescue Errno::ESRCH
puts "Pid #{pid} now dead!!!!"
pids.delete(pid)
running_jobs -= 1
puts "Remaining jobs: #{running_jobs}"
end
end
输出:
25555
25579
25616
Running on pid 25555
Pid 25555 now dead!!!!
Remaining jobs: 2
Running on pid 25616
Pid 25616 now dead!!!!
Remaining jobs: 1
如您所见,循环永远不会在中间元素上执行。谁能告诉我为什么会这样?我需要真正遍历每个项目并相应地处理它。
答案 0 :(得分:6)
当您使用pids.delete(pid)
迭代数组时,您正在改变数组。因此,您在索引0处于25555,然后删除它,导致数组看起来像[25579, 25616]
。然后你迭代,现在你在索引1,这是25616.如果你只是删除删除,你将不再改变数组,迭代将按预期工作。
答案 1 :(得分:4)
例如,你的循环在第5项,你删除它。第6,7项等向上移动1,当你的循环移动到第6项时,它会找到第7项。
但是说你在迭代它时不能改变你的数组有点笨拙。如果只是将each
替换为reverse_each
,则可以完全按照自己的方式保存代码。这会从头到尾遍历数组,所以现在当你删除第5项时,6向上移动并不重要,因为你接下来要4,而且还没有改变(还有)。
答案 2 :(得分:3)
你在迭代它时不能改变数组 - 只需取出这一行:
pids.delete(pid)
根据您的代码判断,您可能希望像这样重构以模拟delete
调用:
pids = pids.select do |pid|
puts "Running on pid #{pid}"
begin
Process::kill(0, pid)
puts "Pid #{pid} still alive"
true
rescue Errno::ESRCH
puts "Pid #{pid} now dead!!!!"
running_jobs -= 1
puts "Remaining jobs: #{running_jobs}"
false
end
end