क्या उद्देश्य-सी NSString पर स्विच कर सकता है?


166

क्या इसे फिर से लिखने का एक अधिक बुद्धिमान तरीका है?

if ([cardName isEqualToString:@"Six"]) {
    [self setValue:6];
} else if ([cardName isEqualToString:@"Seven"]) {
    [self setValue:7];
} else if ([cardName isEqualToString:@"Eight"]) {
    [self setValue:8];
} else if ([cardName isEqualToString:@"Nine"]) {
    [self setValue:9];
} 

1
नहीं, स्विच केवल int / bool / char / etc प्रकारों पर काम करता है।
chown

यह प्रश्न कुछ इस तरह से है जो केवल एक घंटे पहले ही पोस्ट किया गया था ( stackoverflow.com/questions/8161319/… )
माइकल डौटर्मन

3
इसे करने के कई वैकल्पिक तरीके हैं। जैसे, मान के साथ एक सरणी लोड करें और सरणी में एक मैच की खोज करें। कोई भी बहुत कुशल नहीं है, लेकिन वे कोड दोहराव को कम करते हैं।
हॉट लिक्स

4
एक साइड नोट के रूप में, एप्पल की नई भाषा (स्विफ्ट) अब एक स्विच स्टेटमेंट में तार की तुलना करने की अनुमति देती है!
जेरेडस्मिथ

4
स्विफ्ट पर जाएँ;)
टोटेमेरियो

जवाबों:


147

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

यदि आप कार्ड नाम कर रहे हैं, तो शायद प्रत्येक कार्ड ऑब्जेक्ट को एक पूर्णांक मान प्रदान करें और उस पर स्विच करें। या शायद एक एनम, जिसे एक संख्या के रूप में माना जाता है और इसलिए इसे स्विच किया जा सकता है।

जैसे

typedef enum{
  Ace, Two, Three, Four, Five ... Jack, Queen, King

} CardType;

इस तरह से, ऐस केस 0, टू केस 1, आदि के बराबर होगा।


4
@abbood enum के बारे में अधिक जानकारी के लिए, पोस्टिंग NS_ENUM & NS_OPTIONS मैट थॉम्पसन देखें।
बेसिल बोर्क

@abbood आपकी टिप्पणी का क्या मतलब है? ऐसा लगता है कि यह एक बुरा जवाब है लेकिन मेरे लिए ठीक है। क्या आप समझाएँगे ?
एलन एंड्रेड

जैसा कि मैं समझता हूं, CardTypeकिसी भी संलग्न के बराबर नहीं हो सकता है @""जैसे:[CardType isEqualToString:@"Three"]
एड्रोमिल बलैस

120

आप इस तरह से ब्लॉक का एक शब्दकोश सेट कर सकते हैं:

NSString *lookup = @"Hearts"; // The value you want to switch on

typedef void (^CaseBlock)();

// Squint and this looks like a proper switch!
NSDictionary *d = @{
    @"Diamonds": 
    ^{ 
        NSLog(@"Riches!"); 
    },
    @"Hearts":
    ^{ 
        self.hearts++;
        NSLog(@"Hearts!"); 
    },
    @"Clubs":
    ^{ 
        NSLog(@"Late night coding > late night dancing"); 
    },
    @"Spades":
    ^{ 
        NSLog(@"I'm digging it"); 
    }
};

((CaseBlock)d[lookup])(); // invoke the correct block of code

'डिफ़ॉल्ट' अनुभाग के लिए, अंतिम पंक्ति को निम्न से बदलें:

CaseBlock c = d[lookup];
if (c) c(); else { NSLog(@"Joker"); }

उम्मीद है कि Apple कुछ नए ट्रिक्स सिखाएगा।


35
मैं नहीं बता सकता कि यह वास्तव में बुरा है या वास्तव में अच्छा है। ऐसा करने के बारे में कभी नहीं सोचा होगा, धन्यवाद।
Endy

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

1
यदि आप इसके लिए सिर्फ एक
NS सह

2
हुड के तहत, यह वह तरीका है जो C # बड़े स्विच स्टेटमेंट के लिए करता है।
हांक

78

मेरे लिए, एक अच्छा आसान तरीका:

NSString *theString = @"item3";   // The one we want to switch on
NSArray *items = @[@"item1", @"item2", @"item3"];
int item = [items indexOfObject:theString];
switch (item) {
    case 0:
       // Item 1
       break;
    case 1:
       // Item 2
       break;
    case 2:
       // Item 3
       break;
    default:
       break;
}

1
यह मुझे पंसद है। यह इस समस्या के उत्तर की तलाश में सबसे अधिक की जरूरतों का जवाब देता है, यह जावास्क्रिप्ट में एक समान स्विच की तुलना में बहुत अधिक टाइपिंग नहीं लेता है, और यह मानव पठनीय है।
इव पैरिस

4
मैं जेएस स्विच के साथ इस हैक की तुलना नहीं करूंगा। यदि अगला प्रोग्रामर आइटम 1 और आइटम 2 के बीच कोई आइटम जोड़ता है, तो क्या होता है? बग को शुरू करने के लिए बहुत अधिक संभावनाएं
Aras

हालांकि यह एक अच्छा हैक है, इसलिए मैं आपको प्रयास के लिए अंगूठे देता हूं :)
अरस

@ आरा यदि अगले प्रोग्रामर को एक नई प्रविष्टि जोड़ने की आवश्यकता है, तो वे इसे संभालने के लिए अंत में एक नए केस स्टेटमेंट के साथ सरणी के अंत में जोड़ देंगे। इसलिए @ "item0" को सरणी में @ "item3" के बाद जोड़ा जा सकता है, फिर इसे संभालने के लिए एक केस 3 जोड़ें।
sbonkosky

1
मुझे आपकी तरह पूरी तरह से पसंद है। यह बहुत साफ है। मैं श्रेणी लिख रहा हूं और मुझे मेरे साथ स्ट्रिंग करते समय UIColor को वापस करने की आवश्यकता है।
एलिक्स

11

दुर्भाग्य से, स्विच स्टेटमेंट का उपयोग केवल आदिम प्रकारों पर किया जा सकता है। आपके पास संग्रह का उपयोग करते हुए कुछ विकल्प हैं, हालाँकि।

संभवतः एनएसडी में प्रविष्टि के रूप में प्रत्येक मूल्य को संग्रहीत करने के लिए सबसे अच्छा विकल्प होगा।

NSDictionary *stringToNumber = [NSDictionary dictionaryWithObjectsAndKeys:
                                              [NSNumber numberWithInt:6],@"Six",
                                              [NSNumber numberWithInt:7],@"Seven",
                                              [NSNumber numberWithInt:8],@"Eight",
                                              [NSNumber numberWithInt:9],@"Nine",
                                              nil];
NSNumber *number = [stringToNumber objectForKey:cardName];
if(number) [self setValue:[number intValue]];

8

थोड़ा देर से लेकिन भविष्य में किसी के लिए भी मैं यह काम करने में सक्षम था

#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT

यह दिलचस्प है। क्या आप अधिक विस्तृत कर सकते हैं?
चेन ली योंग

6

यहाँ यह लिखने का अधिक बुद्धिमान तरीका है। यह एक का उपयोग करने के NSNumberFormatterमें "वर्तनी-बाहर शैली" :

NSString *cardName = ...;

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterSpellOutStyle];
NSNumber *n = [nf numberFromString:[cardName lowercaseString]];
[self setValue:[n intValue]];
[nf release];

ध्यान दें कि नंबर फॉर्मेटर चाहता है कि स्ट्रिंग को नीचा दिखाया जाए, इसलिए हमें इसे फॉर्मेटर में पास करने से पहले खुद करना होगा।


5

ऐसा करने के अन्य तरीके हैं, लेकिन switchउनमें से एक नहीं है।

यदि आपके पास केवल कुछ तार हैं, जैसा कि आपके उदाहरण में, आपके पास कोड ठीक है। यदि आपके पास कई मामले हैं, तो आप स्ट्रिंग्स को एक शब्दकोश में कुंजी के रूप में संग्रहीत कर सकते हैं और संबंधित मूल्य देख सकते हैं:

NSDictionary *cases = @{@"Six" : @6,
                        @"Seven" : @7,
                        //...
                       };

NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
    [self setValue:[value intValue]];
}

4

BY FAR .. मेरा FAVORITE "ObjC Add-On" हैObjectMatcher

objswitch(someObject)
    objcase(@"one") { // Nesting works.
        objswitch(@"b")
            objcase(@"a") printf("one/a");
            objcase(@"b") printf("one/b");
            endswitch // Any code can go here, including break/continue/return.
    }
    objcase(@"two") printf("It's TWO.");  // Can omit braces.
    objcase(@"three",     // Can have multiple values in one case.
        nil,              // nil can be a "case" value.
        [self self],      // "Case" values don't have to be constants.
        @"tres", @"trois") { printf("It's a THREE."); }
    defaultcase printf("None of the above."); // Optional default must be at end.
endswitch

और यह गैर-तार के साथ काम करता है, TOO ... छोरों में, यहां तक ​​कि!

for (id ifNumericWhatIsIt in @[@99, @0, @"shnitzel"])
    objswitch(ifNumericWhatIsIt)
        objkind(NSNumber)  printf("It's a NUMBER.... "); 
        objswitch([ifNumericWhatIsIt stringValue])
            objcase(@"3")   printf("It's THREE.\n"); 
            objcase(@"99")  printf("It's NINETY-NINE.\n"); 
            defaultcase     printf("some other Number.\n");
       endswitch
    defaultcase printf("It's something else entirely.\n");
endswitch

It's a NUMBER.... It's NINETY-NINE.
It's a NUMBER.... some other Number.
It's something else entirely.

सबसे अच्छी बात यह है कि, एसओ कुछ {...}, :'एस, और ()' एस 'हैं


3

ऑब्जेक्टिव-सी इस पहलू में c से अलग नहीं है, यह केवल c को क्या स्विच कर सकता है (और Npronteger, NSUInteger की तरह प्रीप्रो डेफ, क्योंकि वे अंततः केवल एक अभिन्न प्रकार के लिए टाइप किए गए हैं)।

विकिपीडिया:

सी वाक्यविन्यास :

स्विच स्टेटमेंट के कारण अभिव्यक्ति के मूल्य के आधार पर कई बयानों में से एक को नियंत्रित किया जा सकता है, जिसमें अभिन्न प्रकार होना चाहिए

अभिन्न प्रकार :

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


2

मैं पार्टी में देर से आता हूं, लेकिन कहा गया सवाल का जवाब देने के लिए , अधिक बुद्धिमान तरीका है:

NSInteger index = [@[@"Six", @"Seven", @"Eight", @"Nine"] indexOfObject:cardName];
if (index != NSNotFound) [self setValue: index + 6];

ध्यान दें कि indexOfObjectमैच का उपयोग करने के लिए देखो isEqual:, बिल्कुल सवाल के रूप में।


2

@Graham Perks विचार पर बिल्डिंग पहले से पोस्ट की गई थी, जिसने स्ट्रिंग्स पर स्विचिंग को काफी सरल और साफ बनाने के लिए एक साधारण वर्ग तैयार किया।

@interface Switcher : NSObject

+ (void)switchOnString:(NSString *)tString
                 using:(NSDictionary<NSString *, CaseBlock> *)tCases
           withDefault:(CaseBlock)tDefaultBlock;

@end

@implementation Switcher

+ (void)switchOnString:(NSString *)tString
                 using:(NSDictionary<NSString *, CaseBlock> *)tCases
           withDefault:(CaseBlock)tDefaultBlock
{
    CaseBlock blockToExecute = tCases[tString];
    if (blockToExecute) {
        blockToExecute();
    } else {
        tDefaultBlock();
    }
}

@end

आप इसे इस तरह उपयोग करेंगे:

[Switcher switchOnString:someString
                   using:@{
                               @"Spades":
                               ^{
                                   NSLog(@"Spades block");
                               },
                               @"Hearts":
                               ^{
                                   NSLog(@"Hearts block");
                               },
                               @"Clubs":
                               ^{
                                   NSLog(@"Clubs block");
                               },
                               @"Diamonds":
                               ^{
                                   NSLog(@"Diamonds block");
                               }
                           } withDefault:
                               ^{
                                   NSLog(@"Default block");
                               }
 ];

सही ब्लॉक स्ट्रिंग के अनुसार निष्पादित करेगा।

इस घोल के लिए दें


0

मैं @ जवाब पर कुरकुरा जवाब नहीं दे सकता, लेकिन मैं यह कहना चाहूंगा:

@ कुरसी विधि के लिए एक सीमा है:

टाइप किए गए एनम अल्फ़ान्यूमेरिक मान नहीं लेंगे

typedef enum
{
  12Ace, 23Two, 23Three, 23Four, F22ive ... Jack, Queen, King

} CardType;

तो यहाँ एक और एक है:

लिंक स्टैक ओवर फ्लो इस उपयोगकर्ता के उत्तर पर जाएं "user1717750"


-1
typedef enum
{
    Six,
    Seven,
    Eight
} cardName;

- (void) switchcardName:(NSString *) param {
    switch([[cases objectForKey:param] intValue]) {
        case Six:
            NSLog(@"Six");
            break;
        case Seven:
            NSLog(@"Seven");
            break;
        case Eight:
            NSLog(@"Eight");
            break;
        default: 
            NSLog(@"Default");
            break;
    }
}

कोडिंग का आनंद लें .....

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