Ale*_*exR 5 sorting comparison objective-c nssortdescriptor ios
我有一个自定义对象,其中包含基于时间段的信息,例如endCalYear,endMonth和periodLength属性,它们表示每个句点的结束及其长度.
我想创建一个NSSortDescriptor
基于或者其他排序方法,它结合这三个属性,并允许同时在所有三个键上排序此对象.
例:
EndCalYear endMonth periodLength (months) sortOrder
2012 6 6 1
2012 6 3 2
2012 3 3 3
2011 12 12 4
Run Code Online (Sandbox Code Playgroud)
排序算法将完全根据我自己的算法自行决定.
我怎么能编写这样的算法?
基于块的sortDescriptorWithKey:ascending:comparator:
方法在我的视图中不起作用,因为它允许我只指定一个排序键.但是,我需要同时对所有三个键进行排序.
关于如何解决这个问题的想法或想法?
谢谢!
Nat*_*usa 19
您可以使用块进行排序:
NSArray *sortedArray;
sortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
MyObject *first = (MyObject*)a;
MyObject *second = (MyObject*)b;
if (first.endCalYear < second.endCalYear) {
return NSOrderedAscending;
}
else if (first.endCalYear > second.endCalYear) {
return NSOrderedDescending;
}
// endCalYear is the same
if (first.endMonth < second.endMonth) {
return NSOrderedAscending;
}
else if (first.endMonth > second.endMonth) {
return NSOrderedDescending;
}
// endMonth is the same
if (first.periodLength < second.periodLength) {
return NSOrderedAscending;
}
else if (first.periodLength > second.periodLength) {
return NSOrderedDescending;
}
// periodLength is the same
return NSOrderedSame;
}]
Run Code Online (Sandbox Code Playgroud)
这通过endCalYear
提升,然后endMonth
提升和最终periodLength
提升来排序.您可以修改它以更改顺序或切换if语句中的符号以使其降序.
对于NSFetchedResultsController,您可能想尝试其他方法:
看起来你可以传递一个描述符列表,每个列对应一个你想要排序的列:
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSSortDescriptor *descriptor1 = [[NSSortDescriptor alloc] initWithKey:@"endCalYear" ascending:YES];
NSSortDescriptor *descriptor2 = [[NSSortDescriptor alloc] initWithKey:@"endMonth" ascending:YES];
NSSortDescriptor *descriptor3 = [[NSSortDescriptor alloc] initWithKey:@"periodLength" ascending:YES];
NSArray *sortDescriptors = @[descriptor1, descriptor2, descriptor3];
[fetchRequest setSortDescriptors:sortDescriptors];
Run Code Online (Sandbox Code Playgroud)
用于排序的API通常能够使用一个数组NSSortDescriptors
,而不仅仅是一个,所以为什么不使用它们呢?
例如,NSArray
有一个名为sortedArrayUsingDescriptors:
(注意复数形式)的方法,它采用一组NSSortDescriptor
对象.
所以你可以简单地写一下:
NSSortDescriptor *endCalYearSD = [NSSortDescriptor sortDescriptorWithKey:@"endCalYear" ascending:YES];
NSSortDescriptor *endMonthSD = [NSSortDescriptor sortDescriptorWithKey:@"endMonth" ascending:YES];
NSSortDescriptor *periodLenSD = [NSSortDescriptor sortDescriptorWithKey:@"periodLength" ascending:YES];
NSArray *sortedArray = [originalArray sortedArrayUsingDescriptors:@[endCalYearSD, endMonthSD, periodLenSD]];
Run Code Online (Sandbox Code Playgroud)
这样,您originalArray
将首先按endCalYear排序,每个具有相同endCalYear的条目将按endMonth排序,并且具有相同endCalYear和endMonth的每个条目将按periodLendth排序.
您有API为大多数建议排序的API(包括CoreData等)使用sortDescriptors数组,因此原则始终相同.
如果你真的只需要坚持一个NSSortDescriptor
(并且你的排序算法不够灵活,不能使用基于块的比较器或数组NSSortDescriptors
),你可以简单地为自定义对象提供一个属性来计算你可以使用的值.根据您的排序算法.
例如,将此方法添加到您的自定义类:
-(NSUInteger)sortingIndex {
return endCalYear*10000 + endCalMonth*100 + periodLength;
}
Run Code Online (Sandbox Code Playgroud)
然后对此键/属性进行排序.这不是一个非常干净的阅读和一个非常漂亮的设计模式,但更好的方法是改变你的排序算法API,允许一次排序多个键,所以......
我不明白为什么基于块的API sortDescriptorWithKey:ascending:comparator:
不适合你.你可以NSComparator
在那里指定你需要的任何自定义块,所以这个块可以告诉,给定两个对象,哪一个在另一个之前.你确定哪一个是前一个是你的样子,你只能比较endCalYear
,还是endCalYear
和endMonth
因此没有限制此有关使用多个键排序等等.