फॉर-लूप के अंदर, यदि संभव हो तो क्या मुझे ब्रेक की स्थिति को स्थिति क्षेत्र में स्थानांतरित करना चाहिए? [बन्द है]


48

कभी-कभी मुझे छोरों की आवश्यकता होती है जिन्हें इस तरह से ब्रेक की आवश्यकता होती है:

for(int i=0;i<array.length;i++){
    //some other code
    if(condition){
        break;
    }
}

मैं लिखने में असहज महसूस करता हूं

if(condition){
    break;
}

क्योंकि यह कोड की 3 लाइनों की खपत करता है। और मैंने पाया कि लूप को फिर से लिखा जा सकता है:

                                   ↓
for(int i=0;i<array.length && !condition;i++){
    //some other code
}

तो मेरा सवाल है, क्या यह संभव है कि कोड की पंक्तियों को कम करने के लिए हालत को स्थिति क्षेत्र में स्थानांतरित करने के लिए अच्छा हो?


7
इस पर निर्भर करता है कि conditionविशेष रूप से क्या है।
बरगी

4
एक कारण है कि लूपों के भीतर "ब्रेक" और "जारी" के उपयोग की गलत मनाही है। इसे भी देखें: stackoverflow.com/q/3922599/476681
B 27овић

35
मुझे लगता है कि लाइनों की संख्या ही असली मुद्दा नहीं है। इसे एक लाइन पर लिखा जा सकता था। अगर (शर्त) विराम; मेरी राय में मुद्दा पठनीयता है। मैं व्यक्तिगत रूप से लूप की स्थिति का उपयोग करने के अलावा एक लूप को तोड़ना पसंद करता हूं।
जो

97
क्योंकि यह कोड A की 3 पंक्तियों को खा जाता है , किसी भी शैली को नापसंद करने का बहुत, बहुत बुरा कारण है। IMO "कोड की पंक्तियाँ [ing] उपभोग" कहीं अप्रासंगिक और एक अच्छी बात है। बहुत अधिक लॉजिक को बहुत अधिक लाइनों में रखने की कोशिश करने के परिणामस्वरूप अपठनीय कोड और हार्ड-टू-फाइंड बग मिलते हैं।
एंड्रयू हेनले

3
संभवतः अलोकप्रिय राय: for(int i=0;i<array.length && !condition;i++)अपेक्षाकृत असामान्य है और किसी को केवल कोड को स्किम करने से अनदेखा किया जा सकता है; यह एक के लिए एक अच्छा उपयोग के मामले हो सकता है whileया do whileपाश है, जो अधिक बार पाश परिभाषा में एक से अधिक को तोड़ने की स्थिति है।
जूल्स

जवाबों:


154

आपके द्वारा दिए गए दो उदाहरण कार्यात्मक रूप से समतुल्य नहीं हैं। मूल में, हालत परीक्षण "कुछ अन्य कोड" अनुभाग के बाद किया जाता है, जबकि संशोधित संस्करण में, यह लूप बॉडी की शुरुआत में पहले किया जाता है।

कोड को कभी भी लाइनों की संख्या को कम करने के एकमात्र उद्देश्य से दोबारा नहीं लिखा जाना चाहिए। जाहिर है कि यह एक अच्छा बोनस है जब यह इस तरह से काम करता है, लेकिन इसे कभी भी पठनीयता या शुद्धता की कीमत पर नहीं किया जाना चाहिए।


5
मैं आपकी भावना को समझता हूं, लेकिन मैंने पर्याप्त विरासत कोड को बनाए रखा है, जहां लूप कई सौ लाइनें लंबी है और कई सशर्त विराम हैं। यह डिबगिंग को बहुत कठिन बना देता है जब आप उम्मीद करते हैं कि आप जिस सशर्त ब्रेक की अपेक्षा करते हैं, वह कोड हो, लेकिन पहले वाले कोड ने यह शर्त लगाई थी कि यह पहले सशर्त विराम है। आप उस कोड को कैसे संभालेंगे? उपरोक्त जैसे छोटे उदाहरणों में, उस तरह के सभी सामान्य परिदृश्य को भूलना आसान है।
बेरिन लोरिट्श

84
@BerinLoritsch: इससे निपटने का सही तरीका है कि लूप न हों जो कि कई सौ लाइन लंबी हों!
क्रिस

27
@Walfrat: यदि यह फिर से लिखना एक विकल्प नहीं है तो वास्तव में कोई सवाल नहीं है। यह कहने के बाद कि आप आमतौर पर कोड के ब्लॉक को स्थानांतरित करने के लिए "एक्स्ट्रेक्ट मेथड" प्रकार के रिफैक्टर का उपयोग कर सकते हैं, जिसके चारों ओर आपका मुख्य तरीका लूप को छोटा और उम्मीद है कि तर्क प्रवाह को और अधिक स्पष्ट कर देगा। यह वास्तव में मामला बात से एक मामला है। मैं तरीकों को छोटा रखने के अपने सामान्य नियम के साथ खड़ा रहूंगा और निश्चित रूप से अगले लूप लॉजिक को छोटा रखूंगा, लेकिन मैं सामान्य अर्थ में इससे अधिक कुछ भी कहने की कोशिश नहीं करना चाहता ...
क्रिस

4
@AndrewHenle संक्षिप्तता पठनीयता है, कम से कम इस अर्थ में कि वर्बोसिटी बढ़ने से हमेशा पठनीयता और स्थिरता बनी रहती है । एलओसी को कम करने से घनत्व में वृद्धि और अमूर्त स्तर को बढ़ाकर हासिल किया जाता है, और इस साइट पर अन्य क्यू / ए जोड़े में अटेस्टेड के रूप में बनाए रखने के साथ बहुत कसकर सहसंबद्ध होता है।
लेउशेंको

5
@ जो-ए-डू का निर्माण इतना दुर्लभ है कि यह ट्रिप डेवलपर्स के लिए प्रवण है, जिसे बाद में उस कोड को बनाए रखने की आवश्यकता होती है। कुछ देवों ने वास्तव में उन्हें कभी नहीं देखा! मुझे यकीन नहीं है कि अगर एक ऐसा करते समय पठनीयता में सुधार होता है - यदि कुछ भी, तो यह कोड को समझने में कठिनाई को बढ़ाएगा । एक उदाहरण के रूप में - मेरा वर्तमान कोडबेस लगभग 15 वर्ष पुराना है और लगभग 2 मिलियन LOC है। लगभग पचास डेवलपर्स ने इसे पहले ही छू लिया था। यह बिल्कुल शून्य है, जबकि छोरों!
टी। सर - मोनिका

51

मैं इस तर्क को नहीं खरीदता कि "यह कोड की 3 पंक्तियों का उपभोग करता है" और इस प्रकार यह बुरा है। आखिरकार, आप इसे इस प्रकार लिख सकते हैं:

if (condition) break;

और सिर्फ एक लाइन का उपभोग करें।

यदि ifलूप के माध्यम से आधा रास्ता दिखाई देता है, तो निश्चित रूप से एक अलग परीक्षण के रूप में मौजूद होना चाहिए। हालांकि, यदि यह परीक्षण ब्लॉक के अंत में दिखाई देता है, तो आपने एक लूप बनाया है जिसमें लूप के दोनों सिरों पर परीक्षण जारी रहता है, संभवतः कोड की जटिलता को जोड़ते हुए। हालांकि, ध्यान रखें कि कभी-कभी if (condition)परीक्षण केवल ब्लॉक किए जाने के बाद ही समझ में आता है।

लेकिन यह मानते हुए कि अन्य दृष्टिकोण को अपनाकर ऐसा नहीं है:

for(int i=0;i<array.length && !condition;i++){
    //some other code
}

बाहर निकलने की स्थिति को एक साथ रखा जाता है, जो चीजों को सरल बना सकता है (खासकर अगर " कुछ अन्य कोड लंबा है")।

यहाँ कोई सही जवाब नहीं है। तो भाषा के मुहावरों से अवगत रहें, आपकी टीम के कोडिंग कन्वेंशन आदि क्या हैं, लेकिन संतुलन पर, मैं एकल परीक्षण दृष्टिकोण को अपनाना चाहता हूं जब यह ऐसा करने के लिए कार्यात्मक समझ में आता है।


14
@ jpmc26, बेहतर? मान्य वैकल्पिक शैली? बेशक।
डेविड अर्नो

6
जब कोड को बाद में संपादित किया जाता है, तो गड़बड़ करने के लिए और किसी भी उल्लेखनीय नुकसान से पीड़ित नहीं होना बेहतर होता है।
jpmc26

4
"लूप सामग्री लंबी हो सकती है" के कारण उन्हें एक साथ रखना एक कमजोर तर्क लगता है। जब आपकी सामग्री को पढ़ना कठिन होता है, तो आपको कोड की दो पंक्तियों को सहेजने के अलावा अन्य समस्याएं होती हैं।
ब्लूव्हेल

12
@ jpmc26 असहमत। ब्रेसिज़ इस उत्तर के अनुसार सबसे छोटी, एक-लाइनर स्थिति में अव्यवस्थित अव्यवस्था हैं। बिना आंख पर अधिक सुरुचिपूर्ण और आसान है। वे एक टर्नरी सशर्त ऑपरेटर की तरह हैं। मैं उन्हें बड़े स्टेटमेंट ब्लॉक में तोड़ते हुए ब्रेसिज़ जोड़ना कभी नहीं भूलता; मैं पहले से ही नई कहानियों को जोड़ रहा हूं।
benxyzzy

3
यह सब एक शैली की प्राथमिकता है, लेकिन अगर कोई यह तर्क देता है कि यह सुरक्षित है, तो मैं उस तर्क से असहमत हूं। मैं अपने आप को ब्रेसिज़ के बिना और अगली पंक्ति पर पसंद करते हैं, लेकिन यह किसी भी अधिक या कम अन्य शैलियों से वैध है मतलब नहीं है कि
phflack

49

इस तरह के सवाल ने लगभग उतनी ही बहस छेड़ दी है जितनी देर तक प्रोग्रामिंग चलती रही। अपनी टोपी को रिंग में फेंकने के लिए, मैं इस breakस्थिति के साथ संस्करण के लिए जाऊंगा और यहां क्यों (इस विशिष्ट मामले के लिए):

forपाश पाश में बार-बार दोहराना मान निर्दिष्ट करने के लिए बस नहीं है। भीतर तोड़ने वाली स्थिति को कोडिंग करना केवल तर्क आईएमओ को परेशान करता है।

एक अलग होने breakसे यह स्पष्ट हो जाता है कि सामान्य प्रसंस्करण के दौरान, मान forलूप में निर्दिष्ट होते हैं और प्रसंस्करण को जारी रखना चाहिए सिवाय इसके कि जहां स्थिति आती है।

पृष्ठभूमि के एक बिट के रूप में, मैंने एक कोडिंग शुरू कर दी break, फिर forवर्षों के लिए स्थिति को लूप में डाल दिया (एक असाधारण प्रोग्रामर की दिशा के तहत) और फिर वापस breakशैली में चला गया क्योंकि यह अभी तक क्लीनर महसूस करता था (और प्रचलित शैली में था) विभिन्न कोड टॉम मैं उपभोग कर रहा था)।

यह दिन के अंत में उन पवित्र युद्धों में से एक है - कुछ लोग कहते हैं कि आपको कभी भी कृत्रिम रूप से पाश से बाहर नहीं निकलना चाहिए , अन्यथा यह एक वास्तविक लूप नहीं है। जो भी आपको लगता है वह पठनीय (अपने और दूसरों के लिए दोनों) करें। यदि कीस्ट्रोक्स को कम करना वास्तव में आपकी चीज है, तो सप्ताहांत में कोड गोल्फिंग करें - बीयर वैकल्पिक।


3
यदि स्थिति का एक अच्छा नाम है, जैसे "पाया" (जैसे आप किसी चीज़ के लिए सरणी के माध्यम से देख रहे हैं), तो यह लूप के लिए इसे सिर में रखना एक अच्छा विचार है।
user949300

1
मुझे बताया गया था कि forलूप्स का उपयोग तब किया जाता है जब पुनरावृत्तियों की संख्या ज्ञात हो जाती है (जैसे जब कोई ब्रेकिंग कंडीशन नहीं होती है, लेकिन एरे / लिस्ट का अंत होता है) और whileजब नहीं होते हैं। यह एक whileपाश के लिए मामला लगता है । यदि पठनीयता चिंता का विषय है, idx+=1तो लूप के अंदर एक if/elseब्लॉक की तुलना में पढ़ने के लिए बहुत साफ है
Laiv

यदि आप कोड का अनुसरण कर रहे हैं तो आप ब्रेक की स्थिति को ठीक से नहीं रख सकते, इसलिए कम से कम आपको "if (कंडीशन) {पाया = सही; जारी रखना होगा" लिखना होगा;
gnasher729

हम for(int i=0; i<something;i++)छोरों के लिए उपयोग किए जाते हैं , मुझे लगता है कि आधे डेवलपर्स को वास्तव में याद नहीं है कि forछोरों का उपयोग अलग-अलग तरीके से किया जा सकता है, और इस प्रकार &&conditionभाग को समझने में कठिन समय लगता है ।
राल्फ क्लेरहॉफ

@RalfKleberhoff वास्तव में। मैंने कई नए डेवलपर एक्सप्रेस को आश्चर्यचकित करते हुए देखा है कि ट्रिप्टर स्टेटमेंट एक्सप्रेशन सभी वैकल्पिक हैं। मुझे आखिरी बार यह याद भी नहीं है कि मैंने for(;;)...
रॉबी डी

43

forलूप्स 1 से अधिक के पुनरावृत्ति के लिए होते हैं - वे केवल लोल-लेट-पुल-ऑफ-रैंडम-स्टफ-ए-बॉडी-एंड-ऑफ-द-बॉडी-एंड-ऑफ-द-इन-द-लूप-हेडर नहीं हैं - तीनों भाव बहुत हैं विशिष्ट अर्थ:

  • पहला इटरेटर को इनिशियलाइज़ करने के लिए है । यह एक सूचकांक, एक संकेतक, एक पुनरावृत्ति वस्तु या जो कुछ भी हो सकता है - जब तक कि इसे पुनरावृत्ति के लिए उपयोग किया जाता है ।
  • दूसरा जाँच के लिए है यदि हम अंत तक पहुँच गए हैं।
  • तीसरा पुनरावृति आगे बढ़ाने के लिए है।

विचार लूप के अंदर तर्क से हैंडलिंग हैंडल ( कैसे पुनरावृति करना है) को अलग करना है ( प्रत्येक पुनरावृत्ति में क्या करना है)। कई भाषाओं में आम तौर पर प्रत्येक के लिए एक लूप होता है जो आपको पुनरावृत्ति के विवरण से छुटकारा दिलाता है, लेकिन भले ही आपकी भाषा में वह निर्माण न हो, या यदि यह आपके परिदृश्य में उपयोग नहीं किया जा सकता है - तो भी आपको लूप हेडर को सीमित करना चाहिए यात्रा से निपटने के लिए।

तो, आपको खुद से पूछने की ज़रूरत है - क्या आपकी स्थिति पुनरावृत्ति से निपटने या लूप के अंदर तर्क के बारे में है? संभावना है, यह लूप के अंदर के तर्क के बारे में है - इसलिए इसे हेडर के बजाय लूप के अंदर चेक किया जाना चाहिए।

1 अन्य छोरों के विपरीत, जो कुछ होने के लिए "प्रतीक्षा" कर रहे हैं। ए for/ foreachलूप में आइटम की "सूची" की अवधारणा होनी चाहिए - भले ही वह सूची आलसी या अनंत या अमूर्त हो।


5
यह मेरा पहला विचार था जब मैंने प्रश्न पढ़ा। निराश होकर मुझे किसी को यह कहते हुए देखने के लिए आधा दर्जन उत्तरों को स्क्रॉल करना पड़ा
नेमो

4
उम्म ... सभी लूप्स पुनरावृति के लिए हैं - यही शब्द "पुनरावृत्ति" का अर्थ है :-)। मुझे लगता है कि आप "एक संग्रह पर पुनरावृत्ति", या "एक पुनरावृत्ति का उपयोग कर" की तरह कुछ मतलब है?
17

3
@psmears ठीक है, हो सकता है कि मैंने गलत शब्द चुना हो - अंग्रेजी मेरी मूल भाषा नहीं है, और जब मैं पुनरावृत्ति के बारे में सोचता हूं तो मुझे लगता है कि "कुछ पर चलना"। मैं जवाब ठीक कर दूंगा।
इदं आर्ये

एक मध्यवर्ती मामला वह है जहां हालत कुछ इस तरह है someFunction(array[i])। अब हालत के दोनों हिस्से उस चीज़ के बारे में हैं जो आप पर निर्भर कर रहे हैं, और यह उन्हें &&लूप हेडर के साथ संयोजित करने के लिए समझ में आता है ।
बमर

मैं आपकी स्थिति का सम्मान करता हूं, लेकिन मैं असहमत हूं। मुझे लगता है कि forदिल में छोरों की गिनती होती है, न कि किसी सूची के ऊपर, और यह forपहले की भाषाओं के वाक्यविन्यास द्वारा समर्थित है (इन भाषाओं में अक्सर एक for i = 1 to 10 step 2वाक्यविन्यास होता था , और stepकमांड - यहां तक ​​कि एक प्रारंभिक मूल्य की अनुमति देता है जो पहले का सूचकांक नहीं है। तत्व - एक संख्यात्मक संदर्भ में संकेत, सूची के संदर्भ में नहीं)। केवल उपयोग के मामले मैं समर्थन करता है लगता है कि forके रूप में केवल एक सूची से अधिक पुनरावृत्ति छोरों parallelising है, और उस स्पष्ट वाक्य रचना अब वैसे भी आदेश कर कोड को तोड़ने नहीं करने के लिए, उदाहरण के लिए एक तरह से की आवश्यकता है,।
लोगन पिकअप

8

मैं संस्करण का उपयोग करने की सलाह देता हूं if (condition)। यह अधिक पठनीय और डिबग करने में आसान है। कोड की 3 अतिरिक्त पंक्तियों को लिखने से आपकी उंगलियां नहीं टूटेंगी, लेकिन अगले व्यक्ति के लिए आपके कोड को समझना आसान हो जाएगा।


1
केवल अगर (जैसे टिप्पणी की गई है) लूप ब्लॉक में कोड की सैकड़ों लाइनें नहीं हैं और तर्क तर्क रॉकेट साइंस नहीं है। मुझे लगता है कि आपका तर्क ठीक है, लेकिन मुझे ठीक से याद है कि naming thingsयह समझने के लिए कि क्या चल रहा है और कब टूटने की स्थिति मिलती है।
Laiv

2
@Laiv यदि लूप ब्लॉक के भीतर कोड की सैकड़ों लाइनें हैं, तो सवाल से बड़ी समस्याएं हैं कि ब्रेक की स्थिति को कहां लिखा जाए।
अलेक्जेंडर

इसलिए मैंने उत्तर को प्रासंगिक बनाने का सुझाव दिया, क्योंकि यह हमेशा सच नहीं होता।
लावि

8

यदि आप एक संग्रह पर ध्यान केंद्रित कर रहे हैं, जहां कुछ तत्वों को छोड़ दिया जाना चाहिए, तो मैं एक नया विकल्प सुझाता हूं:

  • पुनरावृति से पहले अपने संग्रह को फ़िल्टर करें

जावा और C # दोनों इसे करने के लिए अपेक्षाकृत तुच्छ बनाते हैं। मुझे आश्चर्य नहीं होगा अगर C ++ के पास कुछ तत्वों को लागू करने के लिए फैंसी इटेटर बनाने का एक तरीका है जो लागू नहीं होता है। लेकिन यह वास्तव में केवल एक विकल्प है यदि आपकी पसंद की भाषा इसका समर्थन करती है, और आपके द्वारा उपयोग किए जाने breakका कारण है क्योंकि आप एक तत्व को संसाधित करते हैं या नहीं, इस पर शर्तें हैं।

अन्यथा आपकी स्थिति को लूप का हिस्सा बनाने का एक बहुत अच्छा कारण है - यह मानते हुए कि यह प्रारंभिक मूल्यांकन सही है।

  • यह देखना आसान है कि लूप कब जल्दी खत्म होता है

मैंने कोड पर काम किया है, जहाँ आपके लूप के लिए कई सशर्त और कुछ जटिल गणित के साथ कुछ सौ लाइनें लगती हैं। इसके साथ आप जो समस्याएं चलाते हैं, वे हैं:

  • break तर्क में दबी हुई आज्ञाओं को खोजना मुश्किल है और कभी-कभी आश्चर्य की बात है
  • डिबगिंग को लूप के प्रत्येक पुनरावृत्ति के माध्यम से कदम उठाने की आवश्यकता होती है ताकि वास्तव में यह समझ सके कि क्या हो रहा है
  • एक कोड के बहुत से आसानी से पुनर्लेखन योग्य उपलब्ध नहीं होता है या एक पुन: लिखने के बाद कार्यात्मक तुल्यता के साथ मदद करने के लिए यूनिट परीक्षण

उस स्थिति में मैं वरीयता के क्रम में निम्नलिखित दिशानिर्देशों की सिफारिश करता हूं :

  • breakयदि संभव हो तो आवश्यकता को समाप्त करने के लिए संग्रह को फ़िल्टर करें
  • लूप शर्तों के लिए सशर्त भाग बनाएं
  • breakयदि संभव हो तो लूप के शीर्ष पर सशर्त रखें
  • ब्रेक पर एक बहु-पंक्ति टिप्पणी जोड़ें, और यह क्यों है

ये दिशानिर्देश हमेशा आपके कोड की शुद्धता के अधीन होते हैं । वह विकल्प चुनें जो आपके इरादे का सबसे अच्छा प्रतिनिधित्व कर सके और आपके कोड की स्पष्टता में सुधार कर सके।


1
इस उत्तर में से अधिकांश ठीक है। लेकिन ... मैं देख सकता हूं कि कैसे एक संग्रह को फ़िल्टर करना continueबयानों की आवश्यकता को समाप्त कर सकता है , लेकिन मैं नहीं देखता कि वे किस तरह से बहुत मदद करते हैं break
user949300

1
@ user949300 एक takeWhileफ़िल्टर breakस्टेटमेंट को बदल सकता है । आप एक है - उदाहरण के लिए जावा केवल उन्हें Jave 9 (नहीं यह है कि कम से हो जाता है कि यह अपने आप को लागू करने के लिए कठिन)
Idan Arye

1
लेकिन जावा में आप अभी भी पुनरावृत्ति से पहले फ़िल्टर कर सकते हैं। धाराओं (1.8 या बाद के) का उपयोग करना या अपाचे संग्रह (1.7 या पूर्व) का उपयोग करना।
Laiv

@IdanArye - ऐसे ऐड-ऑन लाइब्रेरीज़ हैं जो जावा स्ट्रीम API (जैसे JOO-lambda ) में ऐसी सुविधाएं जोड़ते हैं
जूल्स

@IdanArye ने आपकी टिप्पणी से पहले कभी भी एक टेकवाइल के बारे में नहीं सुना। स्पष्ट रूप से फ़िल्टर को ऑर्डर करने के लिए लिंक करना मुझे असामान्य और हैप्पी बनाता है, क्योंकि एक "सामान्य" फिल्टर में हर तत्व सही या गलत वापसी करता है, जो पहले या बाद में आता है। इस तरह आप चीजों को समानांतर में चला सकते हैं।
user949300

8

मैं दृढ़ता से कम से कम आश्चर्य का दृष्टिकोण लेने की सलाह देता हूं जब तक कि आप एक महत्वपूर्ण लाभ प्राप्त नहीं करते हैं।

किसी शब्द को पढ़ते समय लोग हर अक्षर को नहीं पढ़ते हैं, और किताब पढ़ते समय वे हर शब्द नहीं पढ़ते हैं - यदि वे पढ़ने में माहिर हैं, तो वे शब्दों और वाक्यों की रूपरेखा देखते हैं और अपने मस्तिष्क को बाकी हिस्सों में भरने देते हैं। ।

तो संभावना है कि कभी-कभी डेवलपर मान लेंगे कि यह लूप के लिए सिर्फ एक मानक है और इसे भी नहीं देखें:

for(int i=0;i<array.length&&!condition;i++)

यदि आप उस शैली का उपयोग करना चाहते हैं, तो मैं भागों को बदलने की सलाह देता हूं for(int i=0;i<और ;i++)यह पाठक के मस्तिष्क को बताता है कि यह लूप के लिए एक मानक है।


साथ जाने का एक अन्य कारण है if- breakयह है कि आप हमेशा अपने दृष्टिकोण का उपयोग नहीं कर सकते हैं for। आपको उपयोग करना होगा if- breakजब ब्रेक forस्टेटमेंट किसी स्टेटमेंट के भीतर छिपाने के लिए बहुत जटिल है , या उन चर पर निर्भर है जो केवल forलूप के अंदर पहुंच योग्य हैं ।

for(int i=0;i<array.length&&!((someWidth.X==17 && y < someWidth.x/2) || (y == someWidth.x/2 && someWidth.x == 18);i++)

इसलिए यदि आप साथ जाने का फैसला करते हैं if- breakतो आप कवर कर सकते हैं। लेकिन अगर आप for-Conditions के साथ जाने का फैसला करते हैं , तो आपको if- breakand for-ondonditions का उपयोग करना होगा। सुसंगत होने के लिए, आपको शर्तों को बीच में और पीछे ले जाना होगा - जब भी स्थितियां forबदलेंगी ।ifbreak


4

आपका परिवर्तन यह मान रहा है कि जैसे ही आप लूप में प्रवेश करते हैं, उसका conditionमूल्यांकन किया trueजाता है। हम इस उदाहरण में इसकी शुद्धता पर टिप्पणी नहीं कर सकते क्योंकि यह परिभाषित नहीं है।

यहाँ "कोड की लाइनों को कम करने" में सफल होने के बाद, आप तब देखने जा सकते हैं

for(int i=0;i<array.length;i++){
    // some other code
    if(condition){
        break;
    }
    // further code
}

और उसी परिवर्तन को लागू करते हैं, जिस पर पहुंचते हैं

for(int i=0;i<array.length && !condition;i++){
    // some other code
    // further code
}

यह एक अमान्य परिवर्तन है, जैसा कि आप अब बिना शर्त further codeजहां आप पहले नहीं करते थे।

एक अधिक सुरक्षित परिवर्तन योजना एक अलग समारोह में निकालने some other codeऔर मूल्यांकन conditionकरने के लिए है

bool evaluate_condition(int i) // This is an horrible name, but I have no context to improve it
{
     // some other code
     return condition;
}

for(int i=0;i<array.length && !evaluate_condition(i);i++){
    // further code
}

4

टीएल; डीआर जो भी आपकी विशेष परिस्थिति में सबसे अच्छा पढ़ता है

आइए इस उदाहरण को लेते हैं:

for ( int i = 1; i < array.length; i++ ) 
{
    if(something) break;
    // perform operations
}

इस मामले में हम नहीं चाहते हैं कि यदि somethingसही है, तो निष्पादित करने के लिए लूप के लिए कोई भी कोड नहीं है, इसलिए परीक्षण somethingको स्थिति क्षेत्र में ले जाना उचित है।

for ( int i = 1; i < array.length && !something; i++ )

फिर से, इस पर निर्भर करता है कि somethingक्या trueलूप से पहले सेट किया जा सकता है , लेकिन इसके भीतर नहीं, यह अधिक स्पष्टता प्रदान कर सकता है:

if(!something)
{
    for ( int i = 1; i < array.length; i++ )
    {...}
}

अब यह कल्पना करें:

for ( int i = 1; i < array.length; i++ ) 
{
    // perform operations
    if(something) break;
    // perform more operations
}

हम वहां बहुत स्पष्ट संदेश भेज रहे हैं। यदि somethingसरणी को संसाधित करते समय सच हो जाता है तो इस बिंदु पर पूरे ऑपरेशन को छोड़ दें। चेक को उस स्थिति क्षेत्र में ले जाने के लिए, जिसे आपको करने की आवश्यकता है:

for ( int i = 1; i < array.length && !something; i++ ) 
{
    // perform operations
    if(!something)
    {
        // perform more operations
    }
}

तर्क से, "संदेश" कीचड़ हो गई है, और हम दो स्थानों पर विफलता की स्थिति की जांच कर रहे हैं - क्या होगा यदि विफलता की स्थिति बदल जाती है और हम उन स्थानों में से एक को भूल जाते हैं?

बेशक लूप के लिए कई और अलग-अलग आकृतियाँ हैं और उनकी सभी बारीकियों के साथ हालत हो सकती है।

कोड लिखें ताकि यह अच्छी तरह से पढ़े (यह स्पष्ट रूप से कुछ व्यक्तिपरक है) और संक्षिप्त रूप से। कोडिंग दिशानिर्देशों के एक ड्रैकियन सेट के बाहर सभी "नियमों" के अपवाद हैं। आप जो महसूस करते हैं उसे लिखिए, जो निर्णय लेने में सबसे अच्छा है, और भविष्य की गलतियों के लिए अवसरों को कम से कम करें।


2

हालांकि यह आकर्षक हो सकता है क्योंकि आप लूप हैडर में सभी स्थितियों को देखते हैं और breakबड़े ब्लॉकों के अंदर भ्रमित हो सकते हैं, एक forलूप एक पैटर्न है जहां अधिकांश प्रोग्रामर कुछ सीमा से अधिक लूपिंग की उम्मीद करते हैं।

खासकर जब से आप ऐसा करते हैं, एक अतिरिक्त ब्रेक की स्थिति को जोड़ने से भ्रम पैदा हो सकता है और यह देखना कठिन है कि क्या यह कार्यात्मक रूप से समकक्ष है।

अक्सर एक अच्छा विकल्प एक प्रयोग है whileया do {} whileपाश अपने सरणी संभालने कम से कम एक तत्व है जो दोनों की स्थिति की जाँच करता है,।

int i=0
do {
    // some other code
    i++; 
} while(i < array.length && condition);

एक लूप का उपयोग करना जो केवल एक शर्त की जांच कर रहा है और लूप हेडर से कोड नहीं चल रहा है जब आप स्थिति की जांच करते हैं और वास्तविक स्थिति क्या है और साइड इफेक्ट के साथ कोड क्या है।


इस प्रश्न के कुछ अच्छे उत्तर होने के बावजूद, मैं इसे विशेष रूप से अपवोट करना चाहता था क्योंकि यह एक महत्वपूर्ण बिंदु है: मेरे लिए, फॉर-लूप में एक साधारण बाउंड चेकिंग के अलावा कुछ भी होने ( for(...; i <= n; ...)) वास्तव में कोड को पढ़ने के लिए कठिन बनाता है क्योंकि मेरे पास है यहाँ क्या हो रहा है, इसके बारे में सोचने और रोकने के लिए और पहली बार में पूरी तरह से हालत याद कर सकते हैं क्योंकि मुझे उम्मीद नहीं है कि यह वहाँ होगा। मेरे लिए, एक forलूप का अर्थ है कि आप कुछ सीमा पर लूपिंग कर रहे हैं, अगर कोई विशेष निकास स्थिति है, तो इसे ए के साथ स्पष्ट किया जाना चाहिए if, या आप इसका उपयोग कर सकते हैं while
कंप्युटरशिप

1

यह बुरा है, क्योंकि कोड को मनुष्यों द्वारा पढ़ा जाता है - गैर-मुहावरेदार forलूप अक्सर पढ़ने के लिए भ्रमित होते हैं, जिसका अर्थ है कि कीड़े यहां छिपने की अधिक संभावना रखते हैं, लेकिन मूल कोड को दोनों को रखते हुए सुधार करना संभव हो सकता है। छोटा और पठनीय।

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

array.find(item -> item.valid)

इसका समाधान सरल करते हुए इसे कम करना चाहिए क्योंकि आपका कोड विशेष रूप से कहता है कि आपको क्या चाहिए।


1

मेरी राय में कुछ कारण जो कहते हैं, आपको नहीं करना चाहिए।

  1. यह पठनीयता को कम करता है।
  2. आउटपुट समान नहीं हो सकता है। हालांकि, यह do...whileलूप (नहीं while) के साथ किया जा सकता है क्योंकि कुछ कोड निष्पादन के बाद स्थिति की जांच की जाती है।

लेकिन इसके शीर्ष पर, इस पर विचार करें,

for(int i=0;i<array.length;i++){

    // Some other code
    if(condition1){
        break;
    }

    // Some more code
    if(condition1){
        break;
    }

    // Some even more code
}

अब, क्या आप वास्तव में उस forस्थिति में इन शर्तों को जोड़कर इसे प्राप्त कर सकते हैं?


" ओपनियन " क्या है ? क्या आपका मतलब " राय " है?
पीटर मोर्टेंसन

"खुले में कुछ कारण जो आप कहते हैं, आपको नहीं करना चाहिए" से क्या मतलब है ? क्या आप विस्तार से समझा सकते हैं?
पीटर मॉर्टेंसन

0

मुझे लगता है कि हटाना breakएक अच्छा विचार हो सकता है, लेकिन कोड की लाइनों को बचाने के लिए नहीं।

इसके बिना लिखने का फायदा यह breakहै कि लूप के बाद की स्थिति स्पष्ट और स्पष्ट है। जब आप लूप को पूरा करते हैं और प्रोग्राम की अगली लाइन निष्पादित करते हैं, तो आपकी लूप की स्थिति i < array.length && !conditionझूठी रही होगी। इसलिए, या तो iआपकी सरणी लंबाई से अधिक या बराबर थी, या conditionसच है।

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

यह मूल कारण था कि एडगर दीजकस्ट्रा ने "गोटो कंसिस्टर्ड हार्मफुल" लिखा, यह शैली की बात नहीं थी: एक लूप से बाहर निकलना कार्यक्रम की स्थिति के बारे में औपचारिक रूप से कठिन बनाता है। मैंने break;अपने जीवन में बहुत सारे बयान लिखे हैं, और एक वयस्क के रूप में, मैंने एक बार भी लिखा था goto(प्रदर्शन-महत्वपूर्ण आंतरिक लूप के कई स्तरों से बाहर निकलने के लिए और फिर खोज पेड़ की एक अन्य शाखा के साथ जारी रखें)। हालाँकि, मैं returnलूप से एक सशर्त विवरण लिखने की अधिक संभावना रखता हूं (जो लूप के बाद कभी भी कोड नहीं चलाता है और इसलिए अपनी पोस्ट-शर्तों को नहीं मिटा सकता है) break

परिशिष्ट भाग

वास्तव में, समान व्यवहार देने के लिए कोड को फिर से भरना वास्तव में कोड की अधिक लाइनों की आवश्यकता हो सकती है। आपका रीफैक्टरिंग विशेष रूप से कुछ अन्य कोड के लिए मान्य हो सकता है या यदि हम साबित कर सकते हैं कि conditionझूठी शुरुआत होगी। लेकिन आपका उदाहरण सामान्य मामले में बराबर है:

if ( array.length > 0 ) {
  // Some other code.
}
for ( int i = 1; i < array.length && !condition; i++ ) {
  // Some other code.
}

यदि कोई अन्य कोड वन-लाइनर नहीं है, तो आप इसे किसी फ़ंक्शन में स्थानांतरित कर सकते हैं ताकि आप खुद को दोहरा न सकें, और फिर आपने अपने लूप को टेल-पुनरावर्ती फ़ंक्शन में बदल दिया।

मैं मानता हूं कि यह आपके प्रश्न का मुख्य बिंदु नहीं था, हालांकि, और आप इसे सरल बनाए हुए थे।


समस्या यह नहीं है कि ब्रेक कोड के बारे में बहस करना कठिन बनाता है, समस्या यह है कि यादृच्छिक स्थानों पर ब्रेक कोड को जटिल चीजों के लिए बनाता है। यदि वास्तव में इसकी जरूरत है, तो ब्रेक के कारण बहस करना मुश्किल नहीं है, लेकिन क्योंकि कोड को जटिल चीजों को करने की आवश्यकता है।
gnasher729

यहाँ मैं असहमत हूँ: यदि आप जानते हैं कि कोई breakकथन नहीं है, तो आप जानते हैं कि लूप की स्थिति क्या है और जब वह स्थिति गलत होती है तो लूप बंद हो जाता है। अगर वहाँ एक है break? फिर कई तरीके हैं जब लूप समाप्त हो सकता है, और सामान्य स्थिति में, यह पता लगाना कि उनमें से एक लूप को कब रोक सकता है, वस्तुतः हॉल्टिंग समस्या को हल कर रहा है। व्यवहार में, मेरी बड़ी चिंता यह है कि लूप ऐसा दिखता है जैसे यह एक काम करता है, लेकिन वास्तव में, जिसने भी लूप के बाद कोड लिखा था, उसके जटिल तर्क में दफन एक किनारे के मामले को नजरअंदाज कर दिया। लूप स्थिति में सामान को याद करना मुश्किल है।
डेविसलर

0

हां, लेकिन आपका वाक्यविन्यास अपरंपरागत है और इसलिए खराब है (tm)

उम्मीद है कि आपकी भाषा कुछ इस तरह का समर्थन करती है

while(condition) //condition being a condition which if true you want to continue looping
{
    do thing; //your conditionally executed code goes here
    i++; //you can use a counter if you want to reference array items in order of index
}

2
हो सकता है कि मुझे 'कंडीशन' के लिए एक अलग शब्द का इस्तेमाल करना चाहिए था लेकिन इसका मतलब यह नहीं था कि इसका शाब्दिक अर्थ उदाहरण में ठीक उसी स्थिति से है
इवान

1
न केवल लूप के लिए, बल्कि दूर से अपरंपरागत भी नहीं है, वहाँ बिल्कुल कोई कारण नहीं है कि इस रूप का लूप लूप के बराबर से बेहतर है। वास्तव में ज्यादातर लोग कहेंगे कि यह बदतर है, जैसे कि सीपीपी कोर दिशानिर्देश
शॉन बर्टन

2
कुछ लोग सिर्फ रचनात्मक विकल्पों से नफरत करते हैं। या उनके सिर में एक सेट की तुलना में एक अलग तरीके से एक समस्या को देख रहे हैं। या अधिक आम तौर पर, स्मार्ट गधे। मुझे तुम्हारा दर्द भाई लगता है!
मार्टिन माट

1
@ शॉन सॉरी यार, मुझे पता है कि लोग नफरत करते हैं उन्हें कहा जाता है कि वे गलत हैं, लेकिन मैं आपको es.77
ईवान

2
यह whileकोड में राक्षस पर जोर देता है - अपवाद अन्यथा दिनचर्या / सांसारिक कोड में छिपा हुआ है। व्यापार तर्क सामने और केंद्र है, लूपिंग मैकेनिक्स को सब्सक्राइब किया जाता है। यह forलूप विकल्प के लिए "एक मिनट रुको ..." प्रतिक्रिया से बचा जाता है । यह उत्तर समस्या को ठीक करता है। पूरी तरह से वोट।
राडारबॉब

0

यदि आप एक अत्यधिक जटिल forकथन को पढ़ना मुश्किल समझते हैं, तो यह निश्चित रूप से एक वैध चिंता है। वर्टिकल स्पेस को बर्बाद करना भी एक मुद्दा है (यद्यपि कम महत्वपूर्ण है)।

(व्यक्तिगत रूप से मैं इस नियम को नापसंद करता हूं कि ifबयानों में हमेशा ब्रेसिज़ होना चाहिए, जो मोटे तौर पर यहां व्यर्थ खड़ी जगह का कारण है। ध्यान दें कि समस्या ऊर्ध्वाधर स्थान बर्बाद कर रही है। सार्थक लाइनों के साथ ऊर्ध्वाधर स्थान का उपयोग करना समस्या नहीं होनी चाहिए।)

एक विकल्प इसे कई लाइनों में विभाजित करना है। यदि आप वास्तव में जटिल forकथनों का उपयोग कर रहे हैं, तो यह निश्चित रूप से आपको कई चर और शर्तों के साथ करना चाहिए । (यह मेरे लिए ऊर्ध्वाधर स्थान का एक बेहतर उपयोग है, जितना संभव हो उतना सार्थक कुछ पंक्तियाँ देना।)

for (
   int i = 0, j = 0;
   i < array.length && !condition;
   i++, j++
) {
   // stuff
}

एक बेहतर दृष्टिकोण एक अधिक घोषणात्मक और कम अनिवार्य रूप का उपयोग करने की कोशिश करना हो सकता है। यह भाषा के आधार पर अलग-अलग होगा, या इस प्रकार की चीज़ को सक्षम करने के लिए आपको अपने स्वयं के कार्यों को लिखने की आवश्यकता हो सकती है। यह भी निर्भर करता है कि conditionवास्तव में क्या है। संभवत: यह किसी भी तरह से बदलने में सक्षम होना चाहिए, जो कि ऐरे में है।

array
.takeWhile(condition)  // condition can be item => bool or (item, index) => bool
.forEach(doSomething); // doSomething can be item => void or (item, index) => void

एक जटिल या असामान्य forकथन को कई पंक्तियों में विभाजित करना इस पूरी चर्चा में सबसे अच्छा विचार है
user949300

0

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

उस स्थिति में, लूप के बाहर की स्थिति होना काफी स्वाभाविक है। तो मैं शुरू करता हूं

bool found = false;
size_t foundIndex;

और लूप में लिखूंगा

if (condition) {
    found = true;
    foundIndex = i;
    break;
}

पाश के साथ

for (i = 0; i < something && ! found; ++i)

अब लूप में स्थिति की जांच करना काफी स्वाभाविक है। चाहे "ब्रेक" बयान हो, यह निर्भर करता है कि क्या लूप में आगे की प्रक्रिया है जिससे आप बचना चाहते हैं। यदि कुछ प्रसंस्करण की आवश्यकता है और अन्य प्रसंस्करण नहीं है, तो आपके पास कुछ ऐसा हो सकता है

if (! found) { ... }

अपने पाश में कहीं

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.