我如何排序一个NSMutableArray中的自定义对象?

我想要做的事似乎很简单,但我在网上找不到任何答案。 我有一个NSMutableArray对象,并且让我们说他们是'Person'对象。 我想排序NSMutableArray Person.birthDate是一个NSDate

我认为这与这种方法有关:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

在Java中,我会让我的对象实现为Comparable,或者使用Collections.sort和内联自定义比较器......你怎么在Objective-C中做到这一点?


比较方法

要么为你的对象实现一个比较方法:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor(更好)

或者通常甚至更好:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

您可以轻松地通过向数组添加多个键来排序。 使用自定义比较器方法也是可能的。 看看文档。

块(闪亮!)

自Mac OS X 10.6和iOS 4以来,还可以使用块进行排序:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

性能

基于-compare:和基于块的方法通常要比使用NSSortDescriptor快得多,因为后者依赖于KVC。 NSSortDescriptor方法的主要优点在于它提供了一种使用数据而不是代码来定义排序顺序的方法,这使得用户可以方便地进行设置,因此用户可以通过单击标题行对NSTableView进行排序。


请参阅NSMutableArray方法sortUsingFunction:context:

您将需要设置一个比较函数,该函数接受两个对象( Person类型,因为您正在比较两个Person对象)和一个上下文参数。

这两个对象只是Person实例。 第三个对象是一个字符串,例如@“birthDate”。

该函数返回一个NSComparisonResult :它返回NSOrderedAscending如果PersonA.birthDate < PersonB.birthDate 。 它将返回NSOrderedDescending如果PersonA.birthDate > PersonB.birthDate 。 最后,它会返回NSOrderedSame如果PersonA.birthDate == PersonB.birthDate

这是粗略的伪代码; 你需要充实一些日期与另一个日期相比“更少”,“更多”或“相等”的含义(例如比较秒数等):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

如果你想要更紧凑的东西,你可以使用三元运算符:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

如果你做了很多事情,内联可能会加速这一点。


我在iOS 4中使用了一个块。 必须将我的数组元素从id转换为我的类类型。 在这种情况下,它是一个名为Score的类,有一个名为points的属性。

如果数组的元素不是正确的类型,你也需要决定该怎么做,对于这个例子,我只是返回NSOrderedSame ,但是在我的代码中,我通过了一个例外。

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS:这是按降序排列。

链接地址: http://www.djcxy.com/p/1911.html

上一篇: How do I sort an NSMutableArray with custom objects in it?

下一篇: Place Radix Sort