objective-c - 如何对NSMutableArray的自定义对象排序?

  显示原文与译文双语对照的内容

我想做的很简单,但是我在网上找不到任何答案。 我有一个对象的NSMutableArray,假设它们是'人员'对象。 我想把 NSMutableArray 由 Person.birthDate NSDate

我认为它与这个方法有关:


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

在Java中,我将使我的对象实现可以比较的,或者使用内嵌自定义比较器的Collections.sort 。。你在 objective-c 中怎么做?

时间:

比较方法

为对象实现 compare-method:


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

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

NSSortDescriptor ( 更好)

或者通常更好:


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

通过在数组中添加多个键,可以轻松地按多个键排序。 使用自定义comparator-methods也是可能的。 查看文档

块( 发光) !

还可以通过 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];
}];

查看 NSMutableArray 方法 sortUsingFunction:context:

你需要建立一个比较函数需要两个对象( 类型 Person,因为你正在比较两个 Person 对象) 和上下文参数。

这两个对象只是 Person的实例。 第三个对象是字符串,比如 @"birthDate".

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

这是粗略的错误;你需要将一个日期的含义 flesh"较少","更多"或者"等等"作为另一个日期:


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

我在 iOS 4中使用一个块。 必须将数组的元素从标识类型转换为类类型。 在这种情况下,它是一个名为得分的类,带有一个名为点的属性。

你也需要决定要做什么如果你数组的元素不是正确的类型,在本例中我只是 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: 这是按降序排序的。

从 iOS 4开始,你也可以使用块进行排序。

对于这个特定的例子,我假设数组中的对象有一个'位置'方法,它返回一个 NSInteger


NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) {
 if ([obj1 position]> [obj2 position]) { 
 return (NSComparisonResult)NSOrderedDescending;
 }
 if ([obj1 position] <[obj2 position]) {
 return (NSComparisonResult)NSOrderedAscending;
 }
 return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

注意:"排序"数组将是 autoreleased 。

Person 对象需要实现一个方法,说 compare: 将另一个 Person 对象,并返回 NSComparisonResult 根据 2对象之间的关系。

然后你叫 sortedArrayUsingSelector:@selector(compare:) 和应该做的。

还有其他方法,但据我所知,没有Cocoa-equiv接口的。 使用 sortedArrayUsingSelector: 可能是最无痛的方式。

我试过了,但这对我很有用。 在一个类中,我有另一个名为"现场"的类,并想通过"现场"的属性进行排序。

这就像一个魅力 !


NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];


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

感谢你的工作。。

在 gs 2和答案中缺少一个步骤,工作正常。


NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
 ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptor:sortDescriptors];

( 我没有写在评论中,因为我刚刚登录,没有信誉,我无法评论:-/)

iOS 4块将保存你:)


featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b) {
 DMSeatFeature *first = ( DMSeatFeature* ) a;
 DMSeatFeature *second = ( DMSeatFeature* ) b;

 if ( first.quality == second.quality )
 return NSOrderedSame;
 else
 {
 if ( eSeatQualityGreen == m_seatQuality
 || eSeatQualityYellowGreen == m_seatQuality
 || eSeatQualityDefault == m_seatQuality )
 {
 if ( first.quality <second.quality )
 return NSOrderedAscending;
 else
 return NSOrderedDescending;
 }
 else//eSeatQualityRed || eSeatQualityYellow
 {
 if ( first.quality> second.quality )
 return NSOrderedAscending;
 else
 return NSOrderedDescending;
 }
 }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html 提供了一些描述

...