如何让sortedArrayUsingSelector使用整数而不是字符串进行排序?

发布于 2024-08-30 16:23:07 字数 368 浏览 1 评论 0原文

我有一些这样的数据:

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

如何实施? thz u。

I have some data like this :

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

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

If I run this code, it sorted like this:

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

but I actually want this:

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

How can I implement it? thz u.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一城柳絮吹成雪 2024-09-06 16:23:07

扩展 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];
}

Expanding on Paul Lynch's answer, here's an example I have doing exactly this using a comparison method as a category on NSString. This code handles only the case of numbers followed by optional non-numeric qualifiers, but you could extend it to handle cases like "1a10" etc. if desired.

Once you create the category method, you just need to do

[[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];
}
请叫√我孤独 2024-09-06 16:23:07

您可以使用 NSString 的 -[compare:options:] 函数和 NSNumericSearch 选项来比较 NSString 的数值,而不必先将它们转换为 NSIntegers(这可能非常昂贵,特别是在较长的循环中)。

由于您想使用 NSArray,因此可以使用 NSSortDescriptor 的 +[sortDescriptorWithKey:ascending:comparator:] (或者如果您想要一个相同的 -initWithKey:ascending:comparator:预保留对象)函数来进行基于块的比较,如下所示:

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

使用此方法进行排序将得到与 David 的答案相同的结果,但无需自己处理 NSScanner。

You can use NSString's -[compare:options:] function and the NSNumericSearch option to compare NSStrings numerically, without having to convert them to NSIntegers first (which can be quite expensive, especially in longer loops).

Since you want to use an NSArray, you can use NSSortDescriptor's +[sortDescriptorWithKey:ascending:comparator:] (or the identical -initWithKey:ascending:comparator: if you want a pre-retained object) function to do block-based comparisation like this:

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

Sorting using this method will give the same results as David's answer, but without having to deal with NSScanner yourself.

三生池水覆流年 2024-09-06 16:23:07

实现您自己的返回 NSComparisonResult 的方法。如果您愿意,它可以属于一个类别。

Implement your own method that returns NSComparisonResult. It can be in a category if you wish.

も星光 2024-09-06 16:23:07

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

    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);

Sort and Simple Solution..

    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);
沉鱼一梦 2024-09-06 16:23:07

大卫的答案对我有用。不管怎样,我想分享相同答案的 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)
    }
}

David's answer did the trick for me. For what it's worth, I want to share the Swift 1.0 version of the same answer.

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)
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文