2012-12-30 42 views
0

我打破了我的头为什么降序排序不与下面的代码一起工作。我想限制前5的分数和其他逻辑。分数看起来像这样:22/30,12/18,34/38,23/32等我添加/删除SortDescriptor按降序排序,它似乎适用于前3项,但然后没有正确排序。有人可以帮忙吗?NSUSerDefaults与NSMutableArray排序按降序

- (NSMutableArray*) method1:(NSString *) mode byScore: (NSString *) score 
{ 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSMutableArray *array = [[defaults objectForKey:mode]mutableCopy]; 

    if (!array) 
    { 
     array = [[NSMutableArray alloc] init]; 
    } 
    NSLog(@"The content of array is%@", array); 

    if ([array count] < 5) 
    { 
     if (![array containsObject:score]) 
     { 
      [array addObject:score]; 
      // Need to sort here. But not too sure this is the right place 
      NSLog(@"The content of the sorted array upto 5 is%@", array); 
     } 
    } 
    else 
    { 
     if (![array containsObject:score]) 
     { 
      if ([array lastObject] < score) 
      { 
       [array addObject:score]; 
       // Need to sort here before I remove the last object     
       [array removeLastObject]; 
       NSLog(@"The content of the sorted array else is%@",array); 
      } 
     } 
    } 
    [defaults setObject:array forKey:mode]; 
    [defaults synchronize]; 
    // I want the array in NSUserDefaults to be sorted in desc order 
    // don't know what to return here ==> the array object or the defaults object cast to NSMutableArray? 
} 
+1

是排序的代码吗? –

+1

绝对不会返回“将默认对象强制转换为NSMutableArray”。返回数组有一定意义,但是你不确定应该返回什么,这表明你可能根本不需要返回任何东西,返回类型应该是'void'。 –

+0

我更新了我的问题。我正在使用:NSSortDescriptor类按降序排序,但没有工作 – Hema

回答

0

一种方法排序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; 
}]; 

这将排序至少从最大到最大。从最大订购到至少,只需更换

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; 
    } 
} 
+0

我认为这个解决方案可能会更好地为我工作,但我压缩了代码。正如Nate Chandler所说,currentHighscores = [currentHighscores arrayByAddingObject:score];没有做任何事情。请帮助 – Hema

+0

在最新的编辑中,我添加了上面描述的方法“-addScoreToHighscores:withMethod:”的完整代码。 –

+0

可能作出的改进是添加一个类中的方法来'NSArray'名字类似'-pfx_containsFractionStringWithFloatValueEqualToFloatValueForFractionString:'(替换'在项目的前缀pfx'),这将返回'YES'为@“1/2”不只要'@“1/2”'在'currentHighscores'中,而且'@“2/4”'或'@“9/18”'等都在'currentHighscores'中。行'如果([currentHighscores containsObject:得分]!){'随后将被替换'如果([currentHighscores pfx_containsFractionStringWithFloatValueEqualToFloatValueForFractionString:得分]!){'。 –

1

助手功能

​​3210

类别上的NSString

@implementation NSString (Stuff) 

-(float)floatValueForFraction 
{ 
    NSArray * components = [ self componentsSeparatedByString:@"/" ] ; 
    return [ components[0] floatValue ]/[ components[1] floatValue ] ; 
} 

@end 

你的方法:

- (void)addScore:(NSString*)score forMode:(NSString*)mode 
{ 
    NSUserDefaults * defaults = [ NSUserDefaults standardUserDefaults ] ; 
    NSArray * scores = [ defaults objectForKey:mode ] ; 

    scores = scores ? [ scores arrayByAddingObject:score ] : @[ score ] ; 
    scores = [ scores sortedArrayUsingComparator:^(NSString * a, NSString * b){ 
     return CompareFloats([ a floatValueForFraction ], [ b floatValueForFraction ]) ; 
    }] 

    if (scores.count > 5) { scores = [ scores subarrayWithRange:(NSRange){ .length = 5 } ] ; } 

    [ default setObject:scores forKey:mode ] ; 
} 

如果您想在调用此方法后更新高分,请使用[ [ NSUserDefaults standardUserDefaults ] objectForKey:<mode> ]。最好让你的方法做一件事。

+0

这个比较短,但是内特钱德勒的答案更强大。 – nielsbot