2009-04-17 9 views
24

में ब्रेकिंग std :: for_each एल्गोरिदम का उपयोग करते समय मैं एक निश्चित स्थिति संतुष्ट होने पर कैसे टूट सकता हूं?std :: for_each loop

+0

मैं व्यक्तिगत रूप से लूप के लिए जल्दी से बाहर निकलना पसंद नहीं करता। आईएमओ, लूप के लिए केवल तभी उपयोग किया जाना चाहिए जब आपको पूरी तरह से पुन: सक्रिय करने की आवश्यकता हो। यदि आप बीच में तोड़ना चाहते हैं, तो अन्य लूपिंग संरचनाओं पर विचार करें। –

+4

आज़माएं: std :: find_if –

उत्तर

10

आप find_if एल्गोरिदम का उपयोग कर सकते हैं, जो रोक देगा और पुनरावर्तक को वापस कर देगा जहां पुनरावर्तित तत्व पुनरावर्तित तत्व पर लागू होता है। तो जारी रखने/ब्रेक की स्थिति के रूप में एक बूलियन लौटने के लिए आपकी भविष्यवाणी को बदला जाना चाहिए।

हालांकि, यह एक हैक है, इसलिए आप एल्गोरिदम का उपयोग कर सकते हैं।

BOOST_FOREACH का उपयोग करने का एक और तरीका है।

+0

हां मैं ऐसा कर सकता हूं, लेकिन अगर मैं लूप में तत्वों को कुछ परिचालनों को लागू करना चाहता हूं तो स्थिति क्या संतुष्ट हो जाती है? – Naveen

+0

नवीन, उसके साथ क्या है? आप तत्वों पर किसी भी ऑपरेशन कर सकते हैं। फिर किसी भी समय आप "तोड़ सकते हैं" और लूप निकलता है। –

+0

find_if इनपुट इटरेटर स्वीकार करता है, आउटपुट इटरेटर नहीं। फिर, मैं लूप को हाथ से लागू करने की सलाह दूंगा, या BOOST_FOREACH का उपयोग करूंगा। –

2

आप इसे तब तक नहीं कर सकते जब तक कि आप कोई अपवाद नहीं फेंकते, जो एक अच्छा विचार नहीं है क्योंकि आप अपवादों के साथ प्रवाह नियंत्रण नहीं करते हैं।

अद्यतन: स्पष्ट रूप से बूस्ट के लिए a__ach_if है कि सहायता हो सकती है, लेकिन आप बूस्ट का उपयोग नहीं कर रहे हैं।

+0

आपको for_each_if() का उपयोग करने के लिए बढ़ावा देने की आवश्यकता नहीं है। इसे लागू करना आसान है। –

+0

सही है, लेकिन सवाल यह नहीं है कि "मैं for_each_if() को कैसे कार्यान्वित करूं"। –

+0

for_each_if या तो प्रश्न हल नहीं करता है। यह नहीं था "मैं अपने कोड को एक निश्चित बिंदु के बाद तत्वों पर कुछ भी कैसे नहीं कर सकता", लेकिन "मैं पूरी तरह से पुनरावृत्ति को कैसे रोकूं"। अगर पुनरावृत्ति को पहले समाप्त कर दिया गया हो तो पूरी रेंज को पार करने के लिए कुछ गंभीर प्रदर्शन लागत हो सकती है। तो जवाब अपवाद या कुछ भी नहीं है। (जहां कुछ भी नहीं है "फिर से डिजाइन करें ताकि आपको तोड़ने की ज़रूरत न हो, या इसके लिए for_each का उपयोग न करें"। – jalf

13

आप अपने मज़ेदार से अपवाद फेंक कर for_each() से तोड़ सकते हैं। हालांकि यह अक्सर एक अच्छा विचार नहीं है, और विकल्प हैं।

आप अपने मज़ेदार में राज्य को बनाए रख सकते हैं। यदि आप 'ब्रेक' स्थिति का पता लगाते हैं, तो बस अपने मज़ेदार में एक ध्वज सेट करें और फिर प्रत्येक अनुवर्ती पुनरावृत्ति के लिए बस अपने मज़ेदार की चीज़ के बिना वापस आएं। जाहिर है, यह पुनरावृत्ति को रोक नहीं पाएगा, जो बड़े संग्रहों के लिए महंगा हो सकता है, लेकिन यह कम से कम काम को करने से रोक देगा।

यदि आपका संग्रह सॉर्ट किया गया है, तो आप उस तत्व को()) ढूंढ सकते हैं जिसे आप तोड़ना चाहते हैं, फिर शुरू करने के लिए() से तत्व() लौटाएं() लौटाएं।

अंत में, आप for_each_if() लागू कर सकते हैं। यह फिर से पुनरावृत्ति को रोक नहीं देगा लेकिन आपके मज़ेदार का मूल्यांकन नहीं करेगा जो काम करता है अगर भविष्यवाणी झूठी मूल्यांकन करती है। यहां for_each_xxx() के 2 स्वाद हैं, जो एक मान लेता है और ऑपरेटर ==() का मूल्यांकन करने पर काम करता है, और दूसरा जो दो मज़ेदार लेता है; एक तुलना करता है जो तुलना एला find_if(), और दूसरा जो काम करता है अगर तुलना ऑपरेटर सही साबित करता है।

/* --- 

    For each 
    25.1.1 

     template< class InputIterator, class Function, class T> 
      Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f) 

     template< class InputIterator, class Function, class Predicate > 
      Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f) 

    Requires: 

     T is of type EqualityComparable (20.1.1) 

    Effects:  

     Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold: 

      1: *i == value 
      2: pred(*i) != false 

    Returns:  

     f 

    Complexity: 

     At most last - first applications of f 

    --- */ 

    template< class InputIterator, class Function, class Predicate > 
    Function for_each_if(InputIterator first, 
         InputIterator last, 
         Predicate pred, 
         Function f) 
    { 
     for(; first != last; ++first) 
     { 
      if(pred(*first)) 
       f(*first); 
     } 
     return f; 
    }; 

    template< class InputIterator, class Function, class T> 
    Function for_each_equal(InputIterator first, 
          InputIterator last, 
          const T& value, 
          Function f) 
    { 
     for(; first != last; ++first) 
     { 
      if(*first == value) 
       f(*first); 
     } 
     return f; 
    }; 
+0

आप अपवाद फेंक कर तोड़ सकते हैं। लेकिन कुछ मामलों में खोज() समाधान कम से कम – jalf

+0

सच है; अन्य इनपुट को शामिल करने के लिए संपादित प्रतिक्रिया। –

+0

मैंने कोड को पढ़ने के बाद इस जवाब को ऊपर उठाया, लेकिन मुझे कहना होगा कि लूप को तोड़ने के लिए अपवाद फेंकना कभी भी अच्छा विचार नहीं है, जब तक कि आपको वास्तव में स्थिति को फेंकने की आवश्यकता न हो। –

0

आप एक अपवाद फेंक देते हैं। चाहे यह एक अच्छा विचार है या नहीं, एक शैली प्रश्न, गति @ डैन, लेकिन आपके डिजाइन के साथ एक मुद्दा हो सकता है। for_each का उद्देश्य एक प्रकार की कार्यात्मक-प्रोग्रामिंग शैली के लिए है, जो स्पष्ट रूप से मानता है कि आपके फ़ंक्शन को सेट में समान रूप से लागू किया जा सकता है। इसलिए, यदि आप को तोड़ने की आवश्यकता है, तो इसे असामान्य स्थिति से लिया जा सकता है, और इसलिए अपवाद के योग्य।

अन्य समाधान, और एक अधिक "कार्यात्मक" समाधान, आपके फ़ंक्शन को लिखना है ताकि अगर इसका कुछ अनुप्रयोगों पर कोई प्रभाव न हो, तो इसे कोई प्रभाव न दें। इसलिए, उदाहरण के लिए, यदि आपके पास एक संक्षिप्त कार्य था, तो क्या आपने उन मामलों में 0 जोड़ दिया है जिनसे आप "टूटा" होगा।

+3

प्रवाह नियंत्रण के लिए अपवाद फेंकना शैली का मामला नहीं है। यह स्वाद का मामला है। बुरा स्वाद, वह है। –

+1

लगता है जैसे यह स्वाद से अधिक अंधेरे zealotry का मामला है। यह अन्य समाधानों की तुलना में नौकरी, सरल, क्लीनर और अधिक सुंदरता से काम करता है। मैं इस पर चार्ली से सहमत हूं। यदि आपको * for_each से तोड़ने की आवश्यकता है, तो 1) शायद एक अंतर्निहित डिज़ाइन समस्या है, और 2) अपवाद फेंकना सबसे आसान समाधान है। जब तक अपवाद को इतनी स्पष्ट रूप से पृथक किया जा सकता है (यह कोड की एक पंक्ति है जिसे आपको कोशिश/पकड़ में लपेटने की आवश्यकता है), प्रवाह नियंत्रण के लिए इसका उपयोग सहनशील है। – jalf

+0

यह पुरानी एंटी-गेटो zealotry की तरह है। हां, गेटोस हानिकारक हो सकता है, लेकिन कभी-कभी कुछ भाषाओं में वे उपलब्ध विकल्पों में से सबसे अच्छे हैं। –

6

यदि आप कुछ कार्य करना चाहते हैं, जबकि स्थिति संतुष्ट नहीं है, तो शायद आपको std::find_if जैसे कुछ पर एल्गोरिदम बदलने की आवश्यकता है?

+2

यह आसान तरीका है। जब आप रुकना चाहते हैं तो बस सही लौटें। –

4

जैसा कि पहले ही दूसरों के द्वारा दिखाया गया है यह समाधान कि IMHO कोड अंधेरा के साथ ही प्राप्त है।

तो मेरे सुझाव है कि for_each को लूप के लिए नियमित रूप से बदलना है। यह दूसरों को यह अधिक दिखाई देगा कि आप ब्रेक का उपयोग कर रहे हैं (और यहां तक ​​कि जारी भी)।

20

आप std :: any_of (या std :: all_of या std :: none_of) का उपयोग कर सकते हैं उदा। इस तरह:

std::vector<int> a; 
// ...  
std::all_of(a.begin(), a.end(), [&](int val) { 
    // return false if you want to break, true otherwise 
    }); 

बहरहाल, यह एक बेकार समाधान (वापसी मान वास्तव में कुछ के लिए इस्तेमाल नहीं कर रहे हैं) है, और आप से बेहतर कर रहे हैं आप के मालिक हैं पाश लेखन।

+2

सबसे अच्छा जवाब जो वास्तव में – York

+0

में मदद मिली महान जवाब ... – Ash

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