क्या आप एक ग्रूवी "प्रत्येक" बंद से तोड़ सकते हैं?


143

क्या यह breakग्रूवी से संभव है .each{Closure}, या मुझे इसके बजाय एक क्लासिक लूप का उपयोग करना चाहिए?

जवाबों:


194

नहीं, आप बिना अपवाद के "प्रत्येक" को निरस्त नहीं कर सकते। आप एक क्लासिक लूप चाहते हैं यदि आप चाहते हैं कि ब्रेक एक विशेष स्थिति के तहत गर्भपात करे।

वैकल्पिक रूप से, आप प्रत्येक के बजाय "खोज" क्लोजर का उपयोग कर सकते हैं और जब आप ब्रेक करते हैं तो सच लौटाते हैं।

यह उदाहरण पूरी सूची को संसाधित करने से पहले समाप्त हो जाएगा:

def a = [1, 2, 3, 4, 5, 6, 7]

a.find { 
    if (it > 5) return true // break
    println it  // do the stuff that you wanted to before break
    return false // keep looping
}

प्रिंटों

1
2
3
4
5

लेकिन 6 या 7 प्रिंट नहीं करता है।

कस्टम ब्रेक व्यवहार के साथ अपने स्वयं के पुनरावृत्ति तरीकों को लिखना भी वास्तव में आसान है जो क्लोजर स्वीकार करते हैं:

List.metaClass.eachUntilGreaterThanFive = { closure ->
    for ( value in delegate ) {
        if ( value  > 5 ) break
        closure(value)
    }
}

def a = [1, 2, 3, 4, 5, 6, 7]

a.eachUntilGreaterThanFive {
    println it
}

इसके अलावा प्रिंट:

1
2
3
4
5    

3
मैंने एक पैच को ग्रूवी में भी जमा किया है जो एक खोज-पद्धति जोड़ता है जो एक शॉर्ट-सर्कुलेटेड खोज करता है जो क्लोजर से पहला गैर-अशक्त परिणाम देता है। इस पद्धति का उपयोग लगभग सभी स्थितियों को कवर करने के लिए किया जा सकता है जो कोई व्यक्ति एक-दूसरे को जल्दी से बाहर निकालना चाहता है। यह देखने के लिए कि क्या यह स्वीकार हो गया है और लुढ़क गया है (मैं 1.8 से उम्मीद कर रहा हूँ) में पैच की जाँच करूँगा
टेड नालेिड

2
मैंने इस मामले को आजमाया है: a = [१, २, ३, ४, ५, ६, def, def, -१, -२] यह १ २ ३ ४ ५ -१-२ को लौटाता है। तो, "ब्रीक" काम नहीं करता है।
फेट एच। वीयू

सही खोज सही विकल्प है, प्रत्येक रिटर्न से कभी नहीं टूटेगा
पुष्कर

इससे findबेहतर है any- @ मिचल से नीचे दिए गए दूसरे जवाब को देखें कि एक मेरे लिए काम करता है
Rhubarb

टेड नालेड का पैच ग्रूवी के लिए बहुत उपयोगी है। इसके बजाय findResult का उपयोग करें यदि आपको वास्तव में खोज ऑपरेशन से परिणाम की आवश्यकता है और तत्व ही नहीं। Ex: ​def test = [2] test.findResult{ it * 2 }​
डग

57

प्रत्येक लूप को किसी भी बंद के साथ बदलें ।

def list = [1, 2, 3, 4, 5]
list.any { element ->
    if (element == 2)
        return // continue

    println element

    if (element == 3)
        return true // break
}

उत्पादन

1
3

बस एक ट्रिक है। "ब्रेक" के बाद एक बयान होने पर क्या होता है। यह बयान "ब्रेक" से मिलने के बाद भी स्पष्ट रहेगा।
फेट एच। वीयू

2
@P H. VU मैंने वापसी जोड़ी है। "ब्रेक" के बाद के बयान पर अमल नहीं किया जाएगा
मिशल जेड मुदा

1
आपके जवाब के लिए धन्यवाद। आप सही हे। मैं भी आपके जवाब को वोट देता हूं। अधिक: किसी भी विधि को DefaultGroovyMethods में परिभाषित किया गया है और यह एक विधेय फ़ंक्शन है जो एक संग्रह में एक तत्व आपूर्ति की गई समापन को संतुष्ट करता है तो यह सही है।
Phat H. VU

any()इस तरह से उपयोग करना थोड़ा भ्रामक है, लेकिन यह निश्चित रूप से काम करता है और आपको तोड़ने या जारी रखने की क्षमता देता है
vegemite4me

1
@ vegemite4me की तरह, मुझे लगता है कि यह एक "चाल" है, लेकिन आप किसी के अर्थ को अच्छी तरह से नहीं समझते हैं। मुख्यता के लिए, आपको इस समाधान का उपयोग नहीं करना चाहिए।
MatRt

11

नहीं, आप एक अपवाद को फेंकने के बिना ग्रूवी में बंद होने से नहीं टूट सकते। इसके अलावा, आपको नियंत्रण प्रवाह के अपवादों का उपयोग नहीं करना चाहिए।

यदि आप पाते हैं कि आप किसी बंद से बाहर निकलना चाहते हैं, तो आपको पहले यह सोचना चाहिए कि आप ऐसा क्यों करना चाहते हैं और यह कैसे करना है। सबसे पहले गौर करने वाली बात यह हो सकती है कि ग्रूवी (वैचारिक) उच्च श्रेणी के कार्यों में से एक में क्लोजर का प्रतिस्थापन हो सकता है। निम्न उदाहरण:

for ( i in 1..10) { if (i < 5) println i; else return}

हो जाता है

(1..10).each{if (it < 5) println it}

हो जाता है

(1..10).findAll{it < 5}.each{println it} 

जो स्पष्टता में भी मदद करता है। यह आपके कोड के इरादे को बेहतर बताता है।

दिखाए गए उदाहरणों में संभावित दोष यह है कि चलना केवल पहले उदाहरण में ही रुक जाता है। यदि आपके पास प्रदर्शन संबंधी विचार हैं, तो आप इसे तब और वहीं रोकना चाहते हैं।

हालाँकि, अधिकांश उपयोग के मामलों के लिए जो पुनरावृत्तियों को शामिल करते हैं, आप आमतौर पर ग्रूवी के खोज, grep, संग्रह, इंजेक्शन, आदि तरीकों में से एक का सहारा ले सकते हैं। वे आमतौर पर कुछ "कॉन्फ़िगरेशन" लेते हैं और फिर "जानते हैं" कि आपके लिए पुनरावृत्ति कैसे की जाए, ताकि आप वास्तव में जहाँ भी संभव हो, अनिवार्य लूप से बच सकें।


1
"नहीं, आप एक अपवाद को फेंकने के बिना ग्रूवी में बंद होने से नहीं टूट सकते।" यह वही है जो स्केला
OshiP देखें

2

बस विशेष बंद का उपयोग कर

// declare and implement:
def eachWithBreak = { list, Closure c ->
  boolean bBreak = false
  list.each() { it ->
     if (bBreak) return
     bBreak = c(it)
  }
}

def list = [1,2,3,4,5,6]
eachWithBreak list, { it ->
  if (it > 3) return true // break 'eachWithBreak'
  println it
  return false // next it
}

3
और यदि आपके पास 1 बिलियन पंक्तियाँ हैं और पहली कॉल पर आंतरिक क्लोजर सही है, तो आप 1 बिलियन माइनस एक मान पर पुनरावृत्ति करेंगे। :(
sbglasius

-4

(1..10) .प्रत्येक {

यदि (यह <5)

इसे छापें

अन्य

विवरण झूठा है


2
यह बाहर नहीं टूटता है each, यह केवल 4. 4 से बड़ा मान नहीं छापता elseहै। यह बहुत ही अच्छा है, आपका कोड इसके बिना भी ऐसा ही करेगा। इसके अलावा, आप यह साबित कर सकते हैं कि अगर आपने अभी और उसके ठीक पहले इसे eachनहीं तोड़ा है । return falseprintln "not breaking"elsereturn false
स्टेफन वैन डेन अककर

कृपया पठनीयता के लिए अपने कोड को प्रारूपित करने के लिए कम से कम न्यूनतम प्रयास करें। जब आप उत्तर देते हैं और इसे करने के लिए बहुत सारे निर्देश होते हैं, तो एक दृश्य पूर्वावलोकन होता है
Mateusz

-11

आप इससे टूट सकते हैं RETURN। उदाहरण के लिए

  def a = [1, 2, 3, 4, 5, 6, 7]
  def ret = 0
  a.each {def n ->
    if (n > 5) {
      ret = n
      return ret
    }
  }

इससे मेरा काम बनता है!


6
यह वही है जो ओपी ने पूछा था, हालांकि यह स्पष्ट रूप से नहीं है कि उसका क्या मतलब है।
18

क्या मेरे पास एक विवरण हो सकता है कि इसमें नकारात्मक वोट क्यों हैं। यह मुझे उसी अवधारणा के रूप में लगता है जैसा कि शीर्ष उत्तर +133 वोटों के साथ (कम स्पष्टीकरण के साथ) कहता है।
स्कीपी १६'१

1
@Skepi आप बंद होने के ऊपर "ब्रेक" नहीं कर सकते। आप anyसरणी की विधि को वापस करके तोड़ सकते हैं false। आप eachविधि को उसी तरह से नहीं तोड़ सकते ।
नक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.