これを書き換えるよりインテリジェントな方法はありますか?
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];
}
残念ながらできません。これは、switchステートメントの使用において最もよく求められているものの1つであるため、(現在の)Java(およびその他)の時流に乗ることを望みます。
カード名を使用している場合は、おそらく各カードオブジェクトに整数値を割り当ててオンにします。または、おそらく列挙型であり、これは数字と見なされるため、オンに切り替えることができます。
例えば.
typedef enum{
Ace, Two, Three, Four, Five ... Jack, Queen, King
} CardType;
このようにすると、エースはケース0、2はケース1などになります。
次のように、ブロックの辞書を設定できます。
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が「スイッチ」にいくつかの新しいトリックを教えてくれることを願っています。
私にとって、素敵な簡単な方法:
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;
}
残念ながら、switchステートメントはプリミティブ型でのみ使用できます。ただし、コレクションを使用するいくつかのオプションがあります。
おそらく最良のオプションは、各値をNSDictionaryのエントリとして保存することです。
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]];
少し遅れましたが、将来的には誰でも私のためにこれを動作させることができました
#define CASE(str) if ([__s__ isEqualToString:(str)])
#define SWITCH(s) for (NSString *__s__ = (s); ; )
#define DEFAULT
これをよりインテリジェントに書く方法を次に示します。 "spell-out style" でNSNumberFormatter
を使用することです:
NSString *cardName = ...;
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setNumberStyle:NSNumberFormatterSpellOutStyle];
NSNumber *n = [nf numberFromString:[cardName lowercaseString]];
[self setValue:[n intValue]];
[nf release];
数値フォーマッタは文字列を小文字にしたいので、それをフォーマッタに渡す前に自分で行う必要があることに注意してください。
他の方法もありますが、switch
はそれらの1つではありません。
あなたの例のように数個の文字列しかない場合、持っているコードは問題ありません。多くの場合、文字列をキーとして辞書に保存し、対応する値を検索できます。
NSDictionary *cases = @{@"Six" : @6,
@"Seven" : @7,
//...
};
NSNumber *value = [cases objectForKey:cardName];
if (value != nil) {
[self setValue:[value intValue]];
}
BY FAR .. 私のお気に入りの「ObjCアドオン」は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.
何より、SO少数の{...}
、:
、および()
があります
Objective-cはこの点でcと違いはありません。cでできることだけを切り替えることができます(最終的に整数型にtypedefされるだけなので、NSIntegerやNSUIntegerのようなpreproc defも)。
ウィキペディア:
c構文 :
Switchステートメントにより、式の値に応じて、いくつかのステートメントのいずれかに制御が転送されます。は整数型でなければなりません。
積分型 :
コンピュータサイエンスでは、整数は整数データ型のデータであり、数学的な整数の有限サブセットを表すデータ型です。整数データ型はサイズが異なる場合があり、負の値を含むことが許可される場合と許可されない場合があります。
私はパーティーに少し遅れていますが、述べられているように質問に答えるには、もっと賢い方法があります:
NSInteger index = [@[@"Six", @"Seven", @"Eight", @"Nine"] indexOfObject:cardName];
if (index != NSNotFound) [self setValue: index + 6];
indexOfObject
は、質問とまったく同じように、isEqual:
を使用して一致を検索することに注意してください。
@Crisの回答でcrisの回答にコメントすることはできませんが、次のように言いたいと思います。
@crisのメソッドには制限があります。
typedef enumは英数字の値を取りません
typedef enum
{
12Ace, 23Two, 23Three, 23Four, F22ive ... Jack, Queen, King
} CardType;
だからここに別のものがあります:
リンクスタックオーバーフロー このユーザーの回答「user1717750」に移動します
以前に投稿された@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");
}
];
文字列に従って正しいブロックが実行されます。