2012-02-10 83 views
3

我有這樣的:紅寶石環路跳過元素

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  

正如你所看到的,循環從未中間元素上執行。任何人都可以告訴我爲什麼那樣發生?我需要真正地循環每個項目並相應地處理它。

+2

您不想在迭代同一個集合的同時刪除集合中的元素。 (我認爲這在大多數編程語言中都是正確的。)除了@ klochner關於您特定情況的帖子外,還可以查看這些帖子以瞭解從Ruby中的數組中刪除所選項目的其他方式:http://stackoverflow.com/問題/ 3260686/how-can-i-use-arraydelete-while-iterating-over-the-array http://stackoverflow.com/questions/2933366/deleting-while-iterating-in-ruby – Telemachus 2012-02-10 00:24:45

+0

由於某種原因,我覺得就像我已經能夠在我編寫的其他程序中做到的那樣。我將不得不稍後嘗試。我是Ruby的新手,非常感謝幫助。 – jeffcook2150 2012-02-10 00:43:03

回答

6

您在使用pids.delete(pid)進行迭代時突變數組所以,您在位於索引0的25555處,然後將其刪除,導致數組看起來像[25579, 25616]。然後你迭代,現在你在索引1,這是25616.如果你只是刪除刪除,你不會再改變數組,迭代將按預期工作。例如,

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 
+0

爲什麼會導致某些項目被跳過?它應該只是從陣列中刪除當前的PID。我想讓這個數組成爲我試圖追蹤的pid的最新列表,我不想讓一堆死體重在那裏漂浮。 – jeffcook2150 2012-02-10 00:22:59

4

因此,您的循環在項目5上,並將其刪除。項目6,7等向上移動1,當你的循環去到項目6曾經是的地方時,它找到項目7.

但是說你不能在迭代時改變你的數組有點不穩定。如果您只是用reverse_each替換each,您可以完全保留您的代碼。這從頭到尾循環訪問數組,所以現在當你刪除第5項時,6個向上移動並不重要,因爲你接下來要4,而且這還沒有改變。

+0

太棒了,解決了我的問題。 – Nic 2012-07-30 01:22:40