並べ替えへの 1 つのアプローチarray
:
まず、次のようにブロックgetNumeratorAndDenominatorFromScoreString
を定義します。
BOOL (^getNumeratorAndDenominatorFromScoreString)(NSString *, NSInteger *, NSInteger *) = ^(NSString *scoreString, NSInteger *numeratorOut, NSInteger *denominatorOut) {
BOOL res = NO;
NSArray *components = [scoreString componentsSeparatedByString:@"/"];
if (components &&
[components count] == 2) {
res = YES;
if (numeratorOut) {
NSNumber *numeratorNumber = [components objectAtIndex:0];
*numeratorOut = [numeratorNumber integerValue];
}
if (denominatorOut) {
NSNumber *denominatorNumber = [components objectAtIndex:1];
*denominatorOut = [denominatorNumber integerValue];
}
}
return res;
};
次に、このブロックを と一緒に使用し-[NSArray sortedArrayUsingComparator]
て並べ替えますarray
。
NSArray *sortedArray = [array sortedArrayUsingComparator: ^(id obj1, id obj2) {
NSComparisonResult res = NSOrderedSame;
NSString *score1 = (NSString *)obj1;
NSString *score2 = (NSString *)obj2;
NSInteger numerator1, denominator1, numerator2, denominator2;
BOOL res1, res2;
res1 = getNumeratorAndDenominatorFromScoreString(score1, &numerator1, &denominator1);
res2 = getNumeratorAndDenominatorFromScoreString(score2, &numerator2, &denominator2);
if (res1
&& res2) {
CGFloat value1 = ((CGFloat)numerator1)/((CGFloat)denominator1);
CGFloat value2 = ((CGFloat)numerator2)/((CGFloat)denominator2);
if (value1 > value2) {
res = NSOrderedDescending;
} else if (value1 < value2) {
res = NSOrderedAscending;
}
}
return res;
}];
これはarray
、最小から最大の順序になります。大きいものから小さいものへと並べ替えるには、単に置き換えます
if (value1 > value2) {
res = NSOrderedDescending;
} else if (value1 < value2) {
res = NSOrderedAscending;
}
と
if (value1 > value2) {
res = NSOrderedAscending;
} else if (value1 < value2) {
res = NSOrderedDescending;
}
このメソッドの読み取り可能な構造は、[ほとんどではない] 疑似コードになります。
- (void)addScoreToHighscores:(NSString *)score withMethod:(NSString *)mode
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *currentHighscores = [defaults arrayForKey:mode];
if (!currentHighscores) currentHighscores = [NSArray array];
if (![currentHighscores containsObject:score]) {
currentHighscores = [currentHighscores arrayByAddingObject:score];
//sort currentHighscores: adapt the above code so that we have
BOOL (^getNumeratorAndDenominatorFromScoreString)(NSString *, NSInteger *, NSInteger *) = //as above
NSArray *newHighscores = [currentHighscores sortedArrayUsingComparator:^(id obj1, id obj2) {
//as above
}];
//truncate newHighscores
if ([newHighscores count] > 5) {
newHighscores = [newHighscores subarrayWithRange:NSMakeRange(0,5)];
}
[defaults setObject:newHighscores forKey:mode];
} else {
//since score is already in currentHighscores, we're done.
return;
}
}
等しくない文字列のスコアを選別する必要があるが、分数の評価が等しい (@"1/2" と @"5/10") 場合は、より賢くする必要があります。
上でスケッチした完全なコードを次に示します。
- (void)addScoreToHighscores:(NSString *)score withMethod:(NSString *)mode
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *currentHighscores = [defaults arrayForKey:mode];
if (!currentHighscores) currentHighscores = [NSArray array];
if (![currentHighscores containsObject:score]) {
currentHighscores = [currentHighscores arrayByAddingObject:score];
//sort currentHighscores: adapt the above code so that we have
BOOL (^getNumeratorAndDenominatorFromScoreString)(NSString *, NSInteger *, NSInteger *) = ^(NSString *scoreString, NSInteger *numeratorOut, NSInteger *denominatorOut) {
BOOL res = NO;
NSArray *components = [scoreString componentsSeparatedByString:@"/"];
if (components &&
[components count] == 2) {
res = YES;
if (numeratorOut) {
NSNumber *numeratorNumber = [components objectAtIndex:0];
*numeratorOut = [numeratorNumber integerValue];
}
if (denominatorOut) {
NSNumber *denominatorNumber = [components objectAtIndex:1];
*denominatorOut = [denominatorNumber integerValue];
}
}
return res;
};
NSArray *newHighscores = [currentHighscores sortedArrayUsingComparator:^(id obj1, id obj2) {
NSComparisonResult res = NSOrderedSame;
NSString *score1 = (NSString *)obj1;
NSString *score2 = (NSString *)obj2;
NSInteger numerator1, denominator1, numerator2, denominator2;
BOOL res1, res2;
res1 = getNumeratorAndDenominatorFromScoreString(score1, &numerator1, &denominator1);
res2 = getNumeratorAndDenominatorFromScoreString(score2, &numerator2, &denominator2);
if (res1
&& res2) {
CGFloat value1 = ((CGFloat)numerator1)/((CGFloat)denominator1);
CGFloat value2 = ((CGFloat)numerator2)/((CGFloat)denominator2);
if (value1 > value2) {
res = NSOrderedDescending;
} else if (value1 < value2) {
res = NSOrderedAscending;
}
}
return res;
}];
//truncate newHighscores
if ([newHighscores count] > 5) {
newHighscores = [newHighscores subarrayWithRange:NSMakeRange(0,5)];
}
[defaults setObject:newHighscores forKey:mode];
} else {
//since score is already in currentHighscores, we're done.
return;
}
}