2016-08-19 64 views
0

在下列情況下的值:如何從一個嵌套循環到父循環,不止一個層次突破,需要通過嵌套循環提供

xxx.delete_if do |x| 
    yyy.descend do |y| # This is a pathname.descend 
    zzz.each do |z| 
     if x + y == z 
     # Do something 

     # Break all nested loops returning to "xxx.delete_if do |x|" loop 

     # The "xxx.delete_if do |x|" must receive a "true" so that it 
     # can delete the array item 
     end 
    end 
    end 
end 

什麼是實現這一目標的最佳途徑多重嵌套中斷,同時確保我可以通過true值,以便數組項被刪除?

也許我應該使用多個break聲明返回true或使用throw/catch與變量,但我不知道這些是否是最好的答案。


來自這個問題How to break from nested loops in Ruby?不同,因爲它需要父環路接收來自嵌套循環的值。

+2

當有人提出一個可以很容易地通過Google搜索找到的問題時,它會收到很多upvotes,但是當它非常具體並且很難找到像這樣的問題時,它就會被低估。 – buggy3

回答

1

您可以使用多個break語句。

例如:

xxx.delete_if do |x| 
    result = yyy.each do |y| 
    result2 = zzz.each do |z| 
     if x + y == z 
     break true 
     end 
    end 
    break true if result2 == true 
    end 
    result == true 
end 

不過我肯定會在你的特殊情況避免這種情況。

您不應該將變量分配給each的結果。使用mapreduceselectrejectany?all?等代替

更有意義使用any?來達到相同的目的:通常

xxx.delete_if do |x| 
    yyy.any? do |y| 
    zzz.any? do |z| 
     x + y == z 
    end 
    end 
end 
+0

我沒有使用'any?'的艱難,它工作正常,但在我的具體情況下,其中一個循環是'path.descend',因此它需要使用變量。我會用'下降'來更新這個問題。 – buggy3

+0

實際上,在我的情況下,有一種方法是不使用變量,我只是切換了最後兩個循環,所以最後一個是'yyy.descend do | y |',這樣我只需添加一個在它裏面打破「真實」,一切正常。謝謝。 – buggy3

3

throw/catch(NOT raise/rescue)是這樣的我看到完成。

xxx.delete_if do |x| 
    catch(:done) do 
    yyy.each do |y| 
     zzz.each do |z| 
     if x + y == z 
      # Do something 

      throw(:done, true) 
     end 
     end 
    end 
    false 
    end 
end 

事實上,the Pickaxe明確的建議吧:

雖然提高救援的異常機制是偉大的,當事情出錯放棄執行,它有時很高興能夠跳出一些在正常加工過程中深度嵌套構造。這就是catch和throw的用處。當Ruby遇到一個throw時,它會回調調用堆棧,尋找具有匹配符號的catch塊。當它找到它時,Ruby將展開堆棧並終止該塊。如果使用可選的第二個參數調用throw,則該值將作爲catch的值返回。

也就是說,max的#any?建議更適合這個問題。

+0

問題是'delete_if'需要'true'來刪除數組元素。在提出問題之前我已經嘗試了您的解決方案。 – buggy3

+0

因爲我的解決方案有效,所以你沒有嘗試使用可選的第二個參數來拋出。 :) –

+0

我記得也嘗試過,它不起作用,因爲我嘗試了很多不同的解決方案,我會再試一次,看看它是否有效,也許我做錯了什麼。 – buggy3