对存放着字典的数组排序
其实是类似于给excel表格排序。NSArray里面有一些元素,这些元素都是NSDictionary,每个元素的keys都是一样的,想要对这样的数据来排序,可以使用到NSSortDescriptor
我先是看到NSHipster上的这篇文章,它是新构造一个类,每个key都是这个类的一个属性,使用如下代码来排序:
@interface Person : NSObject
@property NSString *firstName;
@property NSString *lastName;
@property NSNumber *age;
@end
@implementation Person
- (NSString *)description {
return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end
NSArray *firstNames = @[ @"Alice", @"Bob", @"Charlie", @"Quentin" ];
NSArray *lastNames = @[ @"Smith", @"Jones", @"Smith", @"Alberts" ];
NSArray *ages = @[ @24, @27, @33, @31 ];
NSMutableArray *people = [NSMutableArray array];
[firstNames enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Person *person = [[Person alloc] init];
person.firstName = [firstNames objectAtIndex:idx];
person.lastName = [lastNames objectAtIndex:idx];
person.age = [ages objectAtIndex:idx];
[people addObject:person];
}];
NSSortDescriptor *firstNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"firstName"
ascending:YES
selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *lastNameSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"lastName"
ascending:YES
selector:@selector(localizedStandardCompare:)];
NSSortDescriptor *ageSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age"
ascending:NO];
NSLog(@"By age: %@", [people sortedArrayUsingDescriptors:@[ageSortDescriptor]]);
// "Charlie Smith", "Quentin Alberts", "Bob Jones", "Alice Smith"
NSLog(@"By first name: %@", [people sortedArrayUsingDescriptors:@[firstNameSortDescriptor]]);
// "Alice Smith", "Bob Jones", "Charlie Smith", "Quentin Alberts"
NSLog(@"By last name, first name: %@", [people sortedArrayUsingDescriptors:@[lastNameSortDescriptor, firstNameSortDescriptor]]);
// "Quentin Alberts", "Bob Jones", "Alice Smith", "Charlie Smith"
记得Java里面很多类都有toString()这个方法,觉得真是方便极了。而在objc中,相似的方法就是[xxx description]
,不过你可以重写这个方法,来达到你想要的效果。
上面这种把key当做一个类的属性的方法确实很好,但如果数据是从网上获取的,你事先不知道数据里的key都是一些什么,而runtime又不支持动态地为类添加成员变量。
这也让我苦恼了一小会儿,直到看到这篇文章。
试想一下,你从网上获取一段JSON数据,它大概是像excel表格一样,你要根据里面的字段来对数据进行排序该如何做?
首先,把JSON数据转换成数组。
其次,数组里的都是一个个字典。那么就可以使用如下方法,来实现排序:
NSArray *people = @[
@{@"surname":@"Simpson", @"given":@"Homer", @"title":@"Mr"},
@{@"surname":@"Simpson", @"given":@"Marge", @"title":@"Mrs"},
@{@"surname":@"Simpson", @"given":@"Bart", @"title":@"Mr"},
@{@"surname":@"Simpson", @"given":@"Lisa", @"title":@"Miss"},
@{@"surname":@"Simpson", @"given":@"Maggie", @"title":@"Miss"},
@{@"surname":@"Flanders", @"given":@"Ned", @"title":@"Mr"}
];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"surname" ascending:YES];
NSSortDescriptor *givenDescriptor = [[NSSortDescriptor alloc] initWithKey:@"given" ascending:YES];
NSArray *sortDescriptors = @[nameDescriptor, givenDescriptor];
NSArray *ordered = [people sortedArrayUsingDescriptors:sortDescriptors];
NSSortDescriptor的一些方法
+ sortDescriptorWithKey:ascending:
和- initWithKey:ascending:
这两个方法传入key,和排序方式(升序 or 降序)就能进行排序。如果你key对应的是NSString,那么就按照字符串排序【即@“123”是小于@“2”的】,如果key对应的是NSNumber,那么就按照数字排序。
+ sortDescriptorWithKey:ascending:selector:
和-initWithKey:ascending:selector:
这两个方法可以让你自己指定用来排序的函数。
+ sortDescriptorWithKey:ascending:comparator:
和nitWithKey:ascending:comparator:
可以让你自己来指定判断大小的方法。例如以下代码:
[[NSSortDescriptor alloc] initWithKey:colName ascending:asc comparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
if ([obj1 floatValue] > [obj2 floatValue]){
return (NSComparisonResult)NSOrderedDescending;
}else if ([obj1 floatValue] < [obj2 floatValue]){
return (NSComparisonResult)NSOrderedAscending;
}
else{
return (NSComparisonResult)NSOrderedSame;
}