2010-05-02 66 views
6

我有这样一些数据:如何让sortedArrayUsingSelector使用整数来排序而不是String?

1,111 2,333,45,67,322,4445

NSArray *array = [[myData allKeys]sortedArrayUsingSelector: @selector(compare:)]; 

如果我运行此代码,它排序如下:

1,111,2,322,333,4445,45,67,

,但其实我是想这样的:

1,2,45,67,111,322,333,4445

我怎样才能实现呢?你好。

+0

数组中的对象是什么类--NSString或NSNumber? – sbooth 2010-05-02 09:34:06

+1

这是NSString ......但我不想改成NSNumber。这是因为它将来可能会有像“1a”这样的一些数据。 – Tattat 2010-05-02 09:40:55

+0

1a如何与1和10共处? – Mark 2010-05-02 09:46:40

回答

21

对Paul Lynch的回答进行了扩展,下面是一个使用比较方法作为NSString上的类别完成此操作的示例。此代码仅处理数字后跟可选非数字限定符的情况,但如果需要,可以将其扩展为处理“1a10”等情况。

一旦你创建的类中的方法,你只需要做

[[myData allKeys]sortedArrayUsingSelector:@selector(psuedoNumericCompare:)];

@interface NSString (Support) 
- (NSComparisonResult) psuedoNumericCompare:(NSString *)otherString; 
@end 

@implementation NSString (Support) 

// "psuedo-numeric" comparison 
// -- if both strings begin with digits, numeric comparison on the digits 
// -- if numbers equal (or non-numeric), caseInsensitiveCompare on the remainder 

- (NSComparisonResult) psuedoNumericCompare:(NSString *)otherString { 

    NSString *left = self; 
    NSString *right = otherString; 
    NSInteger leftNumber, rightNumber; 


    NSScanner *leftScanner = [NSScanner scannerWithString:left]; 
    NSScanner *rightScanner = [NSScanner scannerWithString:right]; 

    // if both begin with numbers, numeric comparison takes precedence 
    if ([leftScanner scanInteger:&leftNumber] && [rightScanner scanInteger:&rightNumber]) { 
     if (leftNumber < rightNumber) 
      return NSOrderedAscending; 
     if (leftNumber > rightNumber) 
      return NSOrderedDescending; 

     // if numeric values tied, compare the rest 
     left = [left substringFromIndex:[leftScanner scanLocation]]; 
     right = [right substringFromIndex:[rightScanner scanLocation]]; 
    } 

    return [left caseInsensitiveCompare:right]; 
} 
+0

这真的很棒。正常工作! – Tattat 2010-05-04 13:57:46

+0

这是惊人的,我只是检查它 – kumar 2012-06-13 10:52:19

+0

伟大的,解决了一个问题已经很长时间了! – Tim 2013-05-13 22:39:04

0

实施您自己的方法,返回NSComparisonResult。如果你愿意,它可以在一个类别中。

14

您可以使用NSString的-[compare:options:]功能和NSNumericSearch选项数值比较NSString的,而无需将其转换为NSIntegers首先(这可能相当昂贵,尤其是在较长的循环中)。

由于要使用一个NSArray,可以使用NSSortDescriptor的+[sortDescriptorWithKey:ascending:comparator:](或相同-initWithKey:ascending:comparator:如果想预先保留对象)函数来完成的基于块的comparisation这样的:

[NSSortDescritor sortDescriptorWithKey:@"myKey" 
          ascending:NO 
          comparator:^(id obj1, id obj2) 
    { 
     return [obj1 compare:obj2 options:NSNumericSearch]; 
    } 
]; 

使用排序这种方法会得到与David的答案相同的结果,但不必自己处理NSScanner。

+0

好作品uppfinnarn ..对我很好.. – 2011-12-15 11:07:37

0

排序和简单的解决方案..

NSSortDescriptor *sortDescriptor; 
    sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self" 
                ascending:YES 
                comparator:^(id obj1, id obj2) { 
                 return [obj1 compare:obj2 options:NSNumericSearch]; 
                }]; 
    NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor]; 
    NSArray *sortedArray; 
    sortedArray = [montharray 
        sortedArrayUsingDescriptors:sortDescriptors]; 
    [montharray removeAllObjects]; 
    [montharray addObjectsFromArray:sortedArray]; 

    NSLog(@"MONTH ARRAY :%@",montharray); 
0

大卫answer奏效了我。对于它的价值,我想分享相同答案的Swift 1.0版本。

extension NSString { 
    func psuedoNumericCompare(otherString: NSString) -> NSComparisonResult { 
     var left: NSString = self 
     var right: NSString = otherString 
     var leftNumber: Int = self.integerValue 
     var rightNumber: Int = otherString.integerValue 

     var leftScanner: NSScanner = NSScanner(string: left) 
     var rightScanner: NSScanner = NSScanner(string: right) 

     if leftScanner.scanInteger(&leftNumber) && rightScanner.scanInteger(&rightNumber) { 
      if leftNumber < rightNumber { 
       return NSComparisonResult.OrderedAscending 
      } 
      if leftNumber > rightNumber { 
       return NSComparisonResult.OrderedDescending 
      } 

      left = left.substringFromIndex(leftScanner.scanLocation) 
      right = right.substringFromIndex(rightScanner.scanLocation) 
     } 
     return left.caseInsensitiveCompare(right) 
    } 
} 
相关问题