क्या मुझे स्विच स्टेटमेंट्स का उपयोग करना चाहिए या लंबे समय तक ... और चेन?


36

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

यहाँ कुछ कोड है जो प्रवाह को सामान्य रूप से लिखता है ( diam के लिए धन्यवाद )

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

if (which == 0) {
    comment = "You look so much better than usual.";
} else if (which == 1) {
    comment = "Your work is up to its usual standards.";
} else if (which == 2) {
    comment = "You're quite competent for so little experience.";
} else {
    comment = "Oops -- something is wrong with this code.";
}

फिर वे चाहते हैं कि मैं इसके साथ इसे प्रतिस्थापित करूं:

String comment;   // The generated insult.
int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

switch (which) {
    case 0:  
             comment = "You look so much better than usual.";
    break;
    case 1:  
             comment = "Your work is up to its usual standards.";
    break;
    case 2:  
             comment = "You're quite competent for so little experience.";
    break;
    default: 
             comment = "Oops -- something is wrong with this code.";
}

बहुत अधिक अजीब वाक्यविन्यास में बहुत अधिक कोड की तरह लगता है। लेकिन क्या वास्तव में स्विच स्टेटमेंट का उपयोग करने का एक फायदा है?


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

5
स्टैकओवरफ़्लो पर इस तरह की बहुत चर्चा की गई है: - stackoverflow.com/questions/449273/… - stackoverflow.com/questions/767821/… - stackoverflow.com/questions/97987/vitch-vs-if-else
Yevgeniy Brikman

1
जब भी संभव हो आपको दोनों से बचना चाहिए। डेटा संरचना बनाना और लुकअप करना बहुत बेहतर है, भले ही लुकअप लक्ष्य एक फ़ंक्शन या वर्ग हो।
केविन क्लाइन

स्विच तेज है, कम से कम .net में। मैं जावा के बारे में नहीं जानता।
केंडर्ड

मामलों और विधियों और एक "अगर" के शब्दकोश में
बदला जा सकता है

जवाबों:


57

इस विशेष स्थिति के लिए, यह मुझे लगता है कि दोनों ifऔर caseखराब विकल्प हैं। मैं एक साधारण सरणी का उपयोग करूंगा:

String comments[] = {
    "You look so much better than usual.",
    "Your work is up to its usual standards.",
    "You're quite competent for so little experience."
};

String comment = comments[(int)(Math.random() * 3)];

एक साइड नोट के रूप में, आपको आम तौर पर हार्ड-कोडिंग के बजाय सरणी के आकार के आधार पर गुणक की गणना करनी चाहिए 3

जब आप किसी केस / स्विच का उपयोग करेंगे , तो ifबयानों के कैस्केड से अंतर (या कम से कम एक प्रमुख अंतर) यह होगा कि switchसंख्याओं और मानों के घनत्व के आधार पर अर्ध-स्वचालित रूप से अनुकूलन हो सकता है, जबकि ifबयानों का एक झरना संकलक को छोड़ देता है कम विकल्प के साथ, लेकिन जैसा कि आपने लिखा है, कोड उत्पन्न करने के लिए एक के बाद एक मूल्य का परीक्षण करना जब तक कि यह एक मैच न मिले। केवल तीन वास्तविक मामलों के साथ, यह शायद ही एक चिंता का विषय है, लेकिन पर्याप्त संख्या के साथ यह महत्वपूर्ण हो सकता है।


वह उदाहरण केवल एक उदाहरण था BTW। हालांकि यह नहीं पता था कि संकलक इस तरह का अनुकूलन कर सकता है
TheLQ

6
@JBRWilkinson। इस मामले में, सीमा मूल्य केवल एक कंपाइलर बग के माध्यम से संभव है, जिसे मैं बहुत अधिक समय बिताने के लिए विघटित कर रहा हूं (परिणाम का परीक्षण करने के लिए मेरे कोड में एक बग उत्पन्न होने वाले कोड में होने की संभावना है)। ऐसी स्थिति में जहां सीमा से बाहर मूल्य एक वास्तविक चिंता थी (उदाहरण के लिए, अन्य कोड से इंडेक्स प्राप्त किया जा रहा था) मैं बस पहले सीमा की जांच करूंगा, और चेक के बाद ही इंडेक्स के रूप में इसका उपयोग करूंगा।
जेरी कॉफिन

4
मुझे लगता है कि यह उत्तर उदाहरण के बारे में बहुत ही विशिष्ट है, जबकि यह सवाल उससे कहीं अधिक सामान्य था ...
Khelben

3
@ किचेन: यह मुझे लगता है जैसे आपने पूरे उत्तर को पढ़ने से परेशान नहीं किया। अंतिम पैराग्राफ व्यापक मुद्दों को संबोधित करता है। हालांकि एक समस्या है: मुझे ऐसी बहुत कम स्थितियाँ मिलती हैं जिनमें मैं या तो किसी caseकथन को मानता हूँ या ifउपयुक्त कथनों को कैस्केड करता हूँ । ज्यादातर समय, वे किसी प्रकार के नक्शे / सरणी प्रकार के लिए एक (औसत दर्जे का) विकल्प होते हैं, और आप सीधे बाद वाले में से एक का उपयोग करके बेहतर होते हैं।
जेरी कॉफ़िन

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

23

if...else if...श्रृंखला के साथ समस्या यह है कि जब मैं इसे पढ़ने के लिए आता हूं, तो मुझे यह ifसमझने के लिए हर एक स्थिति को देखना होगा कि कार्यक्रम क्या कर रहा है। उदाहरण के लिए, आपके पास ऐसा कुछ हो सकता है:

if (a == 1) {
    // stuff
} else if (a == 2) {
    // stuff
} else if (a == 3) {
    // stuff
} else if (b == 1) {
    // stuff
} else if (b == 2) {
    // stuff
}

(जाहिर है, इस तरह की एक छोटी संख्या के लिए, यह इतना बुरा नहीं है)

मेरे पास यह जानने का कोई तरीका नहीं है कि आपने हर एक कथन को पढ़े बिना ही स्थिति परिवर्तनशील अर्ध-मार्ग बदल दिया। हालाँकि, क्योंकि switchआप केवल एक ही स्थिति चर के लिए एक सीमा है, मैं एक नज़र में देख सकते हैं कि क्या हो रहा है।

दिन के अंत में, हालांकि, मैं न तो पसंद करेंगे और न ही switchएक श्रृंखला if...else if। अक्सर एक बेहतर समाधान कुछ प्रकार के जंप टेबल या डिक्शनरी होते हैं जैसे कि मूल प्रश्न, या बहुरूपता (यदि आपकी भाषा समर्थन करती है)। यह हमेशा संभव नहीं है, निश्चित रूप से, लेकिन मैं एक ऐसे समाधान की तलाश करूंगा switchजो पहले कदम के रूप में टाल जाए ...


4
बहुरूपता के पास कोड को खंडित करने का नुकसान है, जिससे एक ही स्थान पर होने की तुलना में समझना कठिन हो जाता है। इसलिए आप उस में बदलने से पहले थोड़ा संकोच कर सकते हैं।

एक छलांग तालिका / शब्दकोश एक स्विच से बेहतर क्यों है?
टिटौ

14
switch (which) {
  case 0: comment = "String 1"; break;
  case 1: comment = "String 2"; break;
  case 2: comment = "String 3"; break;
  default: comment = "Oops"; break;
}

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

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


1
यदि आप स्विच को एक विधि में रखते हैं और प्रत्येक मामले returnमें उचित स्ट्रिंग है, तो आप breakकथनों को समाप्त कर सकते हैं ।
रॉबर्ट हार्वे

आपका समाधान भी सबसे तेज़ है।
टिटौ

8

इस मामले में स्विच स्टेटमेंट कोड के इरादे से अधिक स्पष्ट रूप से मेल खाता है: एकल मान के आधार पर कार्रवाई करने के लिए चुनें।

यदि दूसरी ओर के बयानों को पढ़ना बहुत कठिन है - तो आपको उन सभी को देखना होगा जो यह सुनिश्चित कर रहे हैं कि क्या चल रहा है। मेरे लिए यह कम कोड है (भले ही चरित्र गिनती थोड़ी अधिक हो सकती है) क्योंकि मानसिक रूप से पार्स करने के लिए कम है।


8

मैं जेरी से सहमत हूं कि स्ट्रिंग्स की एक सरणी इस विशेष मामले के लिए बेहतर है, लेकिन सामान्य तौर पर यह एक स्विच / केस स्टेटमेंट का उपयोग हनीफ की एक श्रृंखला की तुलना में बेहतर है। यह पढ़ना आसान है, और कभी-कभी कंपाइलर इस तरह से अनुकूलन करने का एक बेहतर काम कर सकते हैं, लेकिन इसके साथ ही एक और लाभ है: यह डिबग करना बहुत आसान है।

जब आप उस स्विच को हिट करते हैं, तो आपको केवल एक बार सही स्टेटस पर समाप्त होने के लिए एक बार कदम उठाना पड़ता है, बजाय इसके कि अगर एक बार में एक स्टेटमेंट को ध्यान से छोड़ दिया जाए, और संभवत: कुंजी को बहुत तेज़ी से हिट किया जाए और उसे पीछे छोड़ दिया जाए और कुछ गायब कर दिया जाए और दुबारा प्रारम्भ करना।


3

मैं उन प्रकार के मामलों में स्विच करना पसंद करता हूं, यह कोड के बिंदु से बहुत बेहतर मेल खाता है, प्रत्येक अलग इनपुट मूल्य के लिए एक अलग स्टेटमेंट निष्पादित करता है। if..elseएक "चाल" एक ही प्रभाव को प्राप्त करने के लिए अधिक की तरह कार्य करता है।

switch बयान भी साफ-सुथरे हैं, उन सभी में एक टाइपो छिपाना आसान है ==

इसके अलावा, सी में बड़े ब्लॉकों के लिए, स्विच तेज है।

else..ifअधिक उपयुक्त हो सकता है जब आपके पास पर्वतमाला (जैसे कि 1 और 100 के बीच, ऐसा करें, 100 और 200 के बीच ऐसा करें), या सी में, जब आप स्ट्रिंग्स जैसे तत्वों के साथ स्विच करने का प्रयास करें (जो कि अन्य भाषाओं में संभव है)। जो एक समान है।

C में प्रोग्राम करते समय मैं बहुत सारे स्विच का उपयोग करता हूं।


2

कुछ ऐसा चुनें, जो कुशल हो, सुस्वादु हो, और फिर आपने जो किया है, उस पर दस्तावेज़ न दें, लेकिन क्यों।

कोड का पुनरीक्षण किया जा सकता है, और हमेशा इसके मूल लेखक द्वारा नहीं।

ऐसे समय होते हैं जब आप जानबूझकर किसी अन्य पर एक कार्यान्वयन चुन सकते हैं क्योंकि आप उस कोड के बारे में आगे-सोच रहे हैं जो मौजूद नहीं है।


2

मुझे आम तौर पर या तो दृष्टिकोण पसंद नहीं है। लंबे स्विच या यदि कथन केवल एक वस्तु उन्मुख अमूर्तता के लिए फिर से शुरू होने की भीख माँगते हैं (हालांकि आपका उदाहरण मैं संक्षिप्त के रूप में वर्गीकृत करूंगा, लंबे समय तक नहीं)।

मैं व्यक्तिगत रूप से उस तरह के कोड को एक अलग सहायक विधि में लपेटूंगा।

private string GetInsult()
{
    int which = (int)(Math.random() * 3);  //  Result is 0, 1, or 2.

    switch (which) {
        case 0: return "You look so much better than usual.";
        case 1: return "Your work is up to its usual standards.";
        case 2: return "You're quite competent for so little experience.";
        default: return "Oops -- something is wrong with this code.";
    }
}

public void Foo()
{
    string comment = GetInsult();
    Print(comment);
}

स्विच को एक अलग विधि में रखने से आप स्विच स्टेटमेंट के अंदर सीधे रिटर्न स्टेटमेंट रख सकते हैं (कम से कम c #), या तो ब्रेक स्टेटमेंट की आवश्यकता को समाप्त कर देते हैं, जिससे कोड को पढ़ने में बहुत आसान हो जाता है।

और यह इमो की तुलना में बहुत अच्छा है अगर / और अगर / अगर दृष्टिकोण।


3
मैं व्यक्तिगत रूप से "इसे दूसरी विधि में रखता हूं क्योंकि यह चीजों को हल करने के लिए बदसूरत दिखता है"। Clutters विधि सूची और खराब IMHO लगती है। मैं केवल ऐसा करूंगा यदि A) कोड को कहीं पर दोहराया गया है या B) कहीं और उपयोगी हो सकता है
TheLQ

1
क्या विधि सूची? और आपके विधि सूची को आपके कोड से क्लॉट किए जाने से बदतर क्यों किया जा रहा है? मैंने सोचा था कि हम अतीत में ले जाया उम्र "एक ही विधि में रखें सब कुछ तो आप एक ही बार में सब कुछ देख सकते"
सारा

@ TheLQ मैं सामान्य रूप से आपसे सहमत हूं, लेकिन इस मामले में "टिप्पणी =" वास्तव में पीट के प्रस्ताव से तथ्यहीन है।
टिटौ

0

अजगर में, कोई स्विच स्टेटमेंट नहीं है, क्योंकि यदि / elif / और अच्छा है:

a = 5

if a==1:
    print "do this"
elif a == 2:
    print "do that"
elif a == 3:
    print "do the other"
elif 3 < a < 9:
    print "do more"
elif 9 <= a < 15:
    print "do nothing"
else:
    print "say sorry"

सरल सही?


Elifबस एक इफ स्टेटमेंट है जिसमें कुछ अक्षर गायब हैं। यह निश्चित रूप से अधिक पसंद हैif से एक स्विच स्टेटमेंट की बयान की । तथ्य यह है कि पायथन में एक स्विच नहीं होता है जो उन्हें नफरत करता है (मेरे जैसे) लगता है कि वे अकेले नहीं हैं।
दान रोसेनस्टार्क

पायथन फॉर्मेटिंग स्टैकओवरफ्लो में काम करता है लेकिन प्रोग्रामर पर नहीं ।stackexchange.com :(
।stackexchange.com

आपको उन्हें सतर्क करना चाहिए metaजब तक यह एक ज्ञात विषय न हो । गिविन के लिए धन्यवाद 'मुझे एक गवाह।
दान रोसेनस्टार्क


1
@ यार, मुझे मेरे विकिपीडिया व्यवस्थापक दिनों की याद दिलाता है ... ओह जॉय। (मैं अभी तक पूरी तरह से विषय हूँ?)
क्रिस्टोफर महान

0

सी / सी # शैली को switchविशेष रूप से कष्टप्रद बनाने वाली चीजों में से एक caseमूल्य शाब्दिक होने का आग्रह है। VB / VB.NET के बारे में एक अच्छी बात यह है कि select/caseप्रत्येक मामले को किसी भी बूलियन अभिव्यक्ति की अनुमति देता है। यह सुविधाजनक है। पारस्परिक रूप से अनन्य बूलियन अभिव्यक्तियों की एक श्रृंखला के रूप में इन्सोफ़र अक्सर सहायक होता है, अगर / और यदि कोई और अधिक लचीला है, तो टाइप और पढ़ने के लिए अधिक कुशल होने का उल्लेख नहीं करने की एक श्रृंखला।

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