如何对包含NSNumbers的NSMutable数组进行排序?

52

我正在尝试制作一个高分榜,但是在Objective-C的数组方面(实际上,在一般的Objective-C中),我表现很差,因此我无法弄清楚如何进行排序。 我正在尝试做这样的事情(伪代码,我正在以ActionScript风格编写此代码,因为我更熟悉它):

highscores.addObjecttoArray(score)
highscores.sort(ascending)

但是我想不出来... 我看到其他帖子谈论它,但他们使用了plist文件和其他东西,而且我不太懂objective c,无法从中学到什么。


你应该学习一下 NSPredicate 和 Predicate 编程主题。理解谓词在 Obj-c 中的作用可以让很多事情变得更容易,但大多数初始培训资源都不会花时间来介绍它。 - TechZen
1
@TechZen,我想你是指NSSortDescriptior吧? - ohhorob
啊,是的。我大脑一半的时间都会坚持将NSSortDescriptior和NSPredicate弄错。不过我的建议还是很实用的,只是离题了。 - TechZen
7个回答

142

你想用简短的方式来做这件事吗?

如果你有一个可变的NSNumber数组:

NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO];
[mutableArrayOfNumbers sortUsingDescriptors:[NSArray arrayWithObject:highestToLowest]];

非常简单 :)

您还可以使用描述符对不可变数组执行类似的排序,但最终会得到一个副本,而不是原地排序。


很好很容易,宝贝 ;) - Atef
1
为了澄清(和优化):NSSortDescriptor *highestToLowest = [NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO]; NSArray * sortedArray = [mutArray sortedArrayUsingDescriptors:@[highestToLowest]]; - mylogon
排序描述符通常用于需要排序的对象实例。您可以指定要用于排序的对象属性作为键。如果是“People”类的实例,您可能会使用“firstName”作为键。在这种情况下,NSNumber对象没有要指定为键的属性,因此使用特殊属性“self”来引用数字本身的值! - ohhorob

28

[highscores sortUsingSelector:@selector(compare:)];

如果这些元素确实都是 NSNumber 类型,这段代码应该能够正常工作。

(添加一个元素的方法是:

[highscores addObject:score];

)

如果想要按照降序排序(即最高分排在最前面):

10.6/iOS 4:

[highscores sortUsingComparator:^(id obj1, id obj2) {
    if (obj1 > obj2)
        return NSOrderedAscending;
    else if (obj1 < obj2)
        return NSOrderedDescending;

    return NSOrderedSame;
}];
否则,您可以定义一个分类方法,例如:
@interface NSNumber (CustomSorting)

- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber;

@end

@implementation NSMutableArray (CustomSorting)

- (NSComparisonResult)reverseCompare:(NSNumber *)otherNumber {
    return [otherNumber compare:self];
}

@end

然后调用它:

[highscores sortUsingSelector:@selector(reverseCompare:)];


好的,小问题,我认为这是错误的排序方式...有没有办法把它调整过来? - meman32
你是指升序和降序吗? - vodkhang
你在问题中提到了升序,但我会编辑它并添加额外的信息。 :) - Wevah
我总是把升序和降序搞混,谢谢你的帮助。 - meman32
(如果回答解决了您的问题,请不要忘记接受答案!;)) - Wevah
1
@Wevah,虽然使用类别或块非常有教育意义,但是对于像这种简单排序的情况,有排序机制(NSSortDescriptor)可用。 - ohhorob

3

我尝试了ohhorob提供的答案,但对象仍然按字母顺序排序。 然后我在另一个答案中找到了这个(https://dev59.com/Z1LTa4cB1Zd3GeqPfPky#4550451):

我改变了我的NSSortDescriptor,现在可以按数字排序。

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"score"
                                               ascending:YES
                                              comparator:^(id obj1, id obj2) {
    return [obj1 compare:obj2 options:NSNumericSearch];
}];

我觉得把这个放在这里是有用的,因为它解决了我的“NSNumbers按字母顺序排序”的问题。


2

以下是另一种简便的方法:

NSArray* n = @[@8, @3, @1, @12, @16, @7, @0, @5];

NSArray* asc = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
            return [n1 compare:n2];
        }];
NSLog(@"Ascending: %@", asc);

NSArray* dec = [n sortedArrayUsingComparator:^NSComparisonResult(NSNumber* n1, NSNumber* n2) {
           return [n2 compare:n1];
       }];
NSLog(@"Descending: %@", dec);

0

距离是一个关键值,它的值链接为浮点数或双精度浮点数

NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"distance"
ascending:YES
comparator:^(id obj1, id obj2)
                     {
                  return [obj1 compare:obj2 options:NSNumericSearch];
                     }];
NSArray *myArray = [NSArray arrayWithArray:arraySubCat];
myArray=[myArray sortedArrayUsingDescriptors:[NSArray arrayWithObjects:sortDescriptor,nil]];
arraySubCat = [myArray copy];

0
这段代码将按升序对NSNumber的NSMutableArray进行排序:
[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2];
}];

这段代码将按降序排列一个NSMutableArray中的NSNumber:
[tempRA sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    return [obj1 compare:obj2] * -1; // reverse the enum
}];

代码利用NSNumber的compare:方法返回一个从-1到1范围内的NSComparisonResult。将比较结果乘以-1可以翻转结果,从而将排序翻转为降序。

1
你可以用 [n2 compare:n1] 替换 [obj1 compare:obj2] - Quamber Ali

-1

降序排列:

NSArray *DescendingArray = [MinMaxArray sortedArrayUsingDescriptors:
                                @[[NSSortDescriptor sortDescriptorWithKey:@"doubleValue"
                                                                ascending:NO]]];

升序排列

NSArray *AscendingArray = [MinMaxArray sortedArrayUsingDescriptors:
                                @[[NSSortDescriptor sortDescriptorWithKey:@"doubleValue"
                                                                ascending:YES]]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接