18

समीक्षा करते समय, मुझे कभी-कभी इस तरह के लूप का सामना करना पड़ता है:क्या लूप में अंतिम तत्व एक अलग उपचार के लायक है?

i = begin 
while (i != end) {  
    // ... do stuff 
    if (i == end-1 (the one-but-last element)) { 
     ... do other stuff 
    } 
    increment i 
} 

फिर मैं सवाल पूछता हूं: क्या आप इसे लिखेंगे?

i = begin 
mid = (end - begin)/2 // (the middle element) 
while (i != end) {  
    // ... do stuff 
    if (i > mid) { 
     ... do other stuff 
    } 
    increment i 
} 

मेरी राय में, यह एक लूप लिखने का इरादा रखता है: आप लूप क्योंकि प्रत्येक तत्व के लिए कुछ सामान्य करना है। इस निर्माण का उपयोग करके, कुछ तत्वों के लिए आप कुछ अलग करते हैं। इसलिए, मैंने निष्कर्ष निकाला है, आपको उन तत्वों के लिए एक अलग लूप की आवश्यकता है:

i = begin 
mid = (end - begin)/2 //(the middle element) 
while (i != mid) {  
    // ... do stuff 
    increment i 
} 

while (i != end) { 
    // ... do stuff 
    // ... do other stuff 
    increment i 
} 

अब मैंने if को SO पर कैसे देखा है if -clause को एक अच्छी तरह से लिखने के तरीके पर ... और मुझे दुख हुआ: कुछ ठीक नहीं है।

क्या मैं गलत हूँ? यदि हां, तो कोडिंग समय पर, विशेष मामलों के साथ लूप बॉडी को अव्यवस्थित करने के बारे में क्या अच्छा है, जिसे आप पहले से जानते हैं?

+0

के मामले यह सब बहुत अच्छा है पर विचार करने देता है। मैं अपनी निजी कार्य शैली में सुधार कर सकता हूं। Thx –

+0

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

+0

@peter_the_oak: मैं मानता हूं कि आप लूप में मिलने वाले मानों के आधार पर निर्णय लेते हैं, लेकिन सूचकांक पर आधारित नहीं हैं। – xtofl

उत्तर

5

@xtofl,

मैं आपकी चिंता से सहमत हूं।

मिलियन बार मुझे इसी तरह की समस्या का सामना करना पड़ा।

या तो डेवलपर पहले के लिए या पिछले तत्व के लिए विशेष हैंडलिंग कहते हैं। 1 तत्व या यहां तक ​​कि कई छोटे छोरों में एक लंबे समय के पाश विभाजित -

ज्यादातर मामलों में यह सिर्फ startIdx + 1 से पाश करने के लिए या endIdx करने के लायक है।

एक बहुत ही दुर्लभ मामलों में यह पाश विभाजित करने के लिए संभव नहीं है में

मेरी राय में असामान्य चीजें जब भी संभव हो लूप के बाहर संभाली जानी चाहिए।

1
बेशक

, एक पाश जो बाहर निकाला जा सकता है में विशेष आवरण बातें मूर्खतापूर्ण है। हालांकि मैं do_stuff को डुप्लिकेट नहीं करता; मैं या तो इसे एक फ़ंक्शन या मैक्रो में रखूंगा ताकि मैं कॉपी-पेस्ट कोड न करूं।

1

कौन सा बेहतर प्रदर्शन करती है?

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

ओह, बेशक आप दो बार पाशन नहीं कर रहे हैं ... जो मामले में दो छोरों बेहतर है। हालांकि, मैं बनाए रखता हूं कि प्राथमिक विचार प्रदर्शन होना चाहिए। लूप (एन टाइम्स) में सशर्त बनाने की कोई आवश्यकता नहीं है यदि आप लूप सीमाओं (एक बार) के सरल हेरफेर द्वारा काम को विभाजित कर सकते हैं।

+0

मैंने कभी दो बार लूपिंग का उल्लेख नहीं किया - मैंने दो हिस्सों में लूप को विभाजित करने का संकेत दिया। – xtofl

10

मैं जानता हूँ कि मैं इस देखा है जब लोगों को अल्पविराम से अलग की स्ट्रिंग में एक सरणी के तत्वों के शामिल होने के लिए करने की कोशिश की:

for(i=0;i<elements.size;i++) { 
    if (i>0) { 
    string += ',' 
    } 
    string += elements[i] 
} 

आप या तो है कि वहाँ में खंड हैं, या आप स्ट्रिंग नकल करने के लिए है + = फिर अंत में लाइन।

इस मामले में स्पष्ट समाधान

string = elements.join(',') 

है लेकिन में शामिल होने के विधि आंतरिक रूप से एक ही पाश करता है। और जो भी आप चाहते हैं उसे करने के लिए हमेशा एक तरीका नहीं है।

5

मैं एक अहसास है कि जब मैं पाश के लिए एक में विशेष मामलों में कहें, मैं आमतौर पर अपने खुद के अच्छे के लिए बहुत चालाक जा रहा हूँ करने के लिए आया था।

2

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

अगर वहाँ विशेष मामलों हालांकि आप शायद अलग निर्माणों में तत्वों के दो अलग सेट से निपटने के लिए किसी तरह के साथ आ बारे में सोचना चाहिए रहे हैं।

1

एक और बात मैं देखना नफरत for-case pattern है:

for (i=0; i<5; i++) 
{ 
    switch(i) 
    { 
    case 0: 
     // something 
     break; 
    case 1: 
     // something else 
     break; 
    // etc... 
    } 
} 

मैं वास्तविक कोड में यह देखा है।

+0

यदि मामले क्रम में निष्पादित होते हैं और कोई सामान्य कोड नहीं है, तो यह मूर्खतापूर्ण प्रतीत होता है। यदि अधिकांश पुनरावृत्तियों को डिफ़ॉल्ट या सामान्य कोड द्वारा नियंत्रित किया जाता है, हालांकि, 'if' परीक्षणों के बजाय' स्विच' के उपयोग के पक्ष में पक्षपात करने के लिए पर्याप्त अपवाद हैं, तो बिखरे हुए विषम मामलों को संभालने के लिए 'स्विच' का उपयोग करने में मुझे कुछ भी गलत नहीं लगेगा (उदाहरण के लिए 1 से 255 तक की एक लूप है और 7, 8, 9, 10, 12, 13, और 27 के इंडेक्स वैल्यू के लिए कुछ अजीब लगती है, लेकिन कभी-कभी प्रोग्रामों को उन चीजों को मॉडल करना पड़ता है जो वास्तविक में अजीब हैं विश्व)। – supercat

19

मुझे नहीं लगता कि इस प्रश्न का एक सिद्धांत द्वारा उत्तर दिया जाना चाहिए (उदाहरण के लिए "एक लूप में, प्रत्येक तत्व को समान रूप से मानें")। इसके बजाय, आप एक कार्यान्वयन अच्छा है या बुरा है अगर मूल्यांकन करने के लिए दो कारकों देख सकते हैं:

  1. रनटाइम effectivity - संकलित कोड तेजी से चलाने करता है, या यह तेजी से इसे दूसरे तरीके से कर रही हैं?
  2. कोड रखरखाव - क्या यह आसान है (किसी अन्य डेवलपर के लिए) यह समझने के लिए कि यहां क्या हो रहा है?

यदि यह तेज़ है और कोड एक लूप में सबकुछ करके अधिक पठनीय है, तो इसे इस तरह से करें। यदि यह धीमा और कम पठनीय है, तो इसे एक और तरीका करें।

यदि यह तेज़ और कम पठनीय, या धीमा लेकिन अधिक पठनीय है, तो पता लगाएं कि आपके विशिष्ट मामले में कौन से कारक अधिक महत्वपूर्ण हैं, और फिर तय करें कि लूप (या लूप नहीं) कैसे करें।

5

पिछले टुकड़ा आप पोस्ट, आप के लिए // कोड दोहरा रहे हैं .... सामान है।

यह आप सूचकांकों का एक अलग सेट पर कार्रवाई की पूरी तरह से अलग सेट है जब 2 छोरों रखने का समझ में आता है।

i = begin 
mid = (end - begin)/2 //(the middle element) 
while (i != mid) {  
    // ... do stuff 
    increment i 
} 

while (i != end) { 
    // ... do other stuff 
    increment i 
} 

यह मामला नहीं है, आप अभी भी एक एकल लूप रखना चाहते हैं। हालांकि तथ्य यह है कि आप अभी भी तुलना (अंत शुरू)/2 तुलनाओं की संख्या बचाते हैं। तो यह नीचे उबलता है कि आप अपने कोड को साफ दिखाना चाहते हैं या आप कुछ सीपीयू चक्रों को सहेजना चाहते हैं। कॉल तुम्हारा है।

0

विशेष मामले के पाश बाहर किया जाना चाहिए अगर यह केवल एक बार प्रदर्शन किया जा करने के लिए।

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

0

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

3

मुझे लगता है कि आपने इसे पूरी तरह से खींचा है। अधिकांश लोग लूप में सशर्त शाखाओं को शामिल करने के जाल में पड़ते हैं, जब वे उन्हें बाहर कर सकते हैं: जो कि तेज है।

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

if(items == null) 
    return null; 

StringBuilder result = new StringBuilder(); 
if(items.Length != 0) 
{ 
    result.Append(items[0]); // Special case outside loop. 
    for(int i = 1; i < items.Length; i++) // Note: we start at element one. 
    { 
     result.Append(";"); 
     result.Append(items[i]); 
    } 
} 
return result.ToString(); 

और मध्य मामले आप वर्णित सिर्फ सादा बुरा है। कल्पना करें कि क्या कोड बढ़ता है और विभिन्न तरीकों से दोबारा काम करने की आवश्यकता है।

जब तक आप XML <grin> पार्स को पार्स नहीं कर रहे हैं, तो लूप को यथासंभव सरल और संक्षिप्त रखना चाहिए।

2

मैं बस, पाश से तत्व को बाहर निकालने और पाश

उदाहरण के लिए बाहर एक spearate उपचार देने के लिए पसंद करते हैं: EOF

i = begin 
while (i != end -1) {  
    // ... do stuff for element from begn to second last element 
    increment i 
} 

if(given_array(end -1) != ''){ 
    // do stuff for the EOF element in the array 
} 
संबंधित मुद्दे