2016-01-06 7 views
23

कोटलिन में, मैं एक फंक्शन लूप और मेरे लैम्ब्डा के भीतर break या continue नहीं कर सकता - जैसे कि मैं सामान्य for लूप से कर सकता हूं। उदाहरण के लिए, इस काम नहीं करता है:कोटलिन के भीतर एक कार्यात्मक लूप में जब मैं "ब्रेक" या "जारी रखें" कैसे करूं?

(1..5).forEach { 
    [email protected] // not allowed, nor [email protected] 
} 

वहाँ old documentation कि इस उपलब्ध होने का उल्लेख है कर रहे हैं लेकिन ऐसा लगता है इसे लागू नहीं किया गया। जब मैं लैम्ब्डा के भीतर से continue या break करना चाहता हूं तो वही व्यवहार प्राप्त करने का सबसे अच्छा तरीका क्या है?

नोट:इस सवाल जानबूझकर लिखा है और लेखक (Self-Answered Questions) द्वारा उत्तर दिया, ताकि मुहावरेदार जवाब आमतौर पर पूछे जाने वाले Kotlin विषयों अतः में मौजूद हैं। कोटलिन के जोर के लिए लिखे गए कुछ वास्तव में पुराने उत्तरों को स्पष्ट करने के लिए जो वर्तमान दिन कोटलिन के लिए सटीक नहीं हैं।

उत्तर

40

आप return from lambda expression जो एक continue या break अपने उपयोग के आधार पर की नकल करता उपयोग कर सकते हैं।

(1..5).forEach { 
    if (it == 3) [email protected] // mimic [email protected] 
    // ... do something more 
} 

और आप और अधिक जटिल जाना और लेबल जब आप घोंसले या भ्रामक स्थितियों होने का उपयोग कर सकते हैं::

यहाँ एक एक उदाहरण नकल उतार continue है

(1..3).forEach [email protected] { x -> 
    (1..3).forEach [email protected] { y -> 
     if (x == 2 && y == 2) [email protected] // mimic [email protected] 
     if (x == 1 && y == 1) [email protected] // mimic [email protected] 
     // ... do something more 
    } 
} 

आप क्या करना चाहते हैं break आपको उस लूप के बाहर कुछ चाहिए जो आप वापस कर सकते हैं, यहां हम run() फ़ंक्शन का उपयोग करने में हमारी सहायता के लिए उपयोग करेंगे:

run [email protected] { 
    (1..20).forEach { x -> 
     if (x == 5) [email protected] // mimic [email protected] 
     // ... do something more 
    } 
} 

के बजाय run() यह let() या apply() या कुछ भी स्वाभाविक रूप से आप forEach कि एक जगह आप से तोड़ने के लिए चाहते हैं आसपास है हो सकता है। लेकिन आप forEach के बाद उसी ब्लॉक में कोड को भी छोड़ देंगे, इसलिए सावधान रहें।

ये इनलाइन फ़ंक्शंस हैं इसलिए वास्तव में वे वास्तव में ओवरहेड नहीं जोड़ते हैं।

अज्ञात कार्यों सहित सभी विशेष मामलों के लिए Returns and Jumps के लिए कोटलिन संदर्भ दस्तावेज़ पढ़ें।

@Test fun testSo32540947() { 
    val results = arrayListOf<Pair<Int,Int>>() 
    (1..3).forEach [email protected] { x -> 
     (1..3).forEach [email protected] { y -> 
      if (x == 2 && y == 2) [email protected] // continue @outer 
      if (x == 1 && y == 1) [email protected] // continue @inner 
      results.add(Pair(x,y)) 
     } 
    } 

    assertEquals(listOf(Pair(1,2), Pair(1,3), Pair(2,1), Pair(3,1), Pair(3,2), Pair(3,3)), results) 

    val results2 = arrayListOf<Int>() 
    run [email protected] { 
     (1..20).forEach { x -> 
      if (x == 5) [email protected] 
      results2.add(x) 
     } 
    } 

    assertEquals(listOf(1,2,3,4), results2) 
} 
+0

खूबसूरती से नहीं, एक और समाधान नहीं है? – store88

1

forEach ब्रेक के साथ विशिष्ट रूप से anyfunction साथ प्रतिस्थापित किया जा सकता:

(1..20).any { x -> 
    (x == 5).apply { // break on true 
     if (!this) { 
      results2.add(x) 
     } 
    } 
} 

या संभवतः भी कम:


यहाँ एक इकाई परीक्षण साबित यह सब काम करता है है

(1..20).any { x -> 
    results2.add(x) 
    x == 4 // break on true 
} 
+1

इसके साथ एकमात्र मुद्दा यह है कि इसे लैम्ब्डा की पहली कॉल पर रोक के रूप में दस्तावेज नहीं किया गया है जो सत्य लौटाता है, और कम स्पष्ट है। यदि आपने कोड में टिप्पणियां नहीं डाली हैं, तो कितने लोग तर्क को याद करेंगे? –

0

takeWhile stdlib फ़ंक्शन का उपयोग ब्रेक के बजाय किया जा सकता है।

उदाहरण के लिए,

val array = arrayOf(2, 8, 4, 5, 13, 12, 16) 
array.takeWhile { it % 2 == 0 }.forEach { println(it) } // break on odd 
array.takeWhile { it % 3 != 0 }.forEach { println(it) } // break on 3 * n 
+0

एक उपयोग उदाहरण आपके उत्तर में सुधार करेगा। –

+1

सावधान रहें कि यह सभी संतोषजनक तत्वों को नए आवंटित मध्यवर्ती संग्रह में कॉपी करेगा। – Vadzim

संबंधित मुद्दे