使用两个特殊键对 NSmutablearray 进行排序
Sort NSmutablearray with two special keys
我有一个表视图,它的 header 存储在一个可变数组中,数组看起来像
(2005 fall, 2005 spring, 2007 summer...)
当我输出tableview时,我想要header按时间升序显示。
2005 spring
2005 fall
2007 summer
我在这里使用了代码:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
[self.sectionKeys sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSString *key = [self.sectionKeys objectAtIndex:section];
return key;
}
与 year
配合使用效果很好。但是,由于字母原因,fall
出现在 spring
和 summer
之前,请问如何解决?
所以你有一个带有节键的数组。但是sections不是按照数组的顺序排列的,需要排序。您会注意到 cellForRowAtIndexPath: 需要完全相同的信息。所以在这个地方排序是错误的。
我如何处理这个问题:我有一个 属性 "unsortedSectionKeys" 和一个 属性 "sortedSectionKeys"。 sortedSectionKeys 有一个 getter 检查 nil 并存储 unsortedSectionKeys 的排序副本,如果它是 nil。每当 unsortedSectionKeys 发生变化时,您只需将 sortedSectionKeys 设置为 nil。 (这至少解决了一些问题)。
对于排序,您需要编写正确的代码。使用 (void)sortUsingComparator:(NSComparator)cmptr 对可变对象进行排序,或 - (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr 获取数组的排序副本。
示例:
[self.sectionKeys sortArrayUsingComparator:^NSComparisonResult(NSString* obj1, NSString* obj2) {
NSInteger year1 = obj1.integerValue;
NSInteger year2 = obj2.integerValue;
if (year1 < year2) return NSOrderedAscending;
if (year1 > year2) return NSOrderedDescending;
NSInteger season1 = 0;
if ([obj1 rangeOfString:@"spring" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 1;
if ([obj1 rangeOfString:@"summer" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 2;
if ([obj1 rangeOfString:@"fall" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 3;
if ([obj1 rangeOfString:@"winter" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 4;
NSInteger season2 = 0;
if ([obj2 rangeOfString:@"spring" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 1;
if ([obj2 rangeOfString:@"summer" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 2;
if ([obj2 rangeOfString:@"fall" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 3;
if ([obj2 rangeOfString:@"winter" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 4;
if (season1 < season2) return NSOrderedAscending;
if (season1 > season2) return NSOrderedDescending;
return NSOrderedSame;
}];
您决定冬天是一年中的第一个还是最后一个季节,因为通常是 12 月到 2 月。
使用自定义比较器获取自定义排序顺序:
NSMutableArray *array = [@[ @"2005 fall", @"2005 spring", @"2007 summer" ] mutableCopy];
NSArray *seasons = @[ @"spring", @"summer", @"fall", @"winter" ];
[array sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
NSArray *parts1 = [str1 componentsSeparatedByString:@" "];
NSArray *parts2 = [str1 componentsSeparatedByString:@" "];
NSString *year1 = parts1[0];
NSString *year2 = parts2[0];
NSComparisonResult yearRes = [year1 compare:year2 options:NSNumericSearch];
if (yearRes == NSOrderedSame) {
NSString *season1 = parts1[1];
NSString *season2 = parts2[1];
NSUInteger index1 = [seasons indexOfObject:season1];
NSUInteger index2 = [seasons indexOfObject:season2];
if (index1 < index2) {
return NSOrderedAscending;
} else if (index1 > index2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
} else {
return yearRes;
}
}];
注意 - 我可能把 NSOrderedAscending
和 NSOrderedDescending
倒过来了。如果同年季节的排序顺序相反,则交换它们。
您需要一种查找机制来定义季节的顺序
NSArray *seasons = @[@"spring", @"summer", @"fall", @"winter"];
NSArray *strings = @[@"2005 fall",@"2007 spring", @"2005 spring", @"2007 winter", @"2005 winter"];
strings = [strings sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSArray *string1Comps = [obj1 componentsSeparatedByString:@" "];
NSArray *string2Comps = [obj2 componentsSeparatedByString:@" "];
NSComparisonResult compareYearResult = [@([string1Comps[0] integerValue]) compare:@([string2Comps[0] integerValue]) ];
if (compareYearResult == NSOrderedSame) {
return [@([seasons indexOfObject:string1Comps[1]]) compare:@([seasons indexOfObject:string2Comps[1]])];
}
return compareYearResult;
}];
结果
(
2005 spring,
2005 fall,
2005 winter,
2007 spring,
2007 winter
)
另一种查找机制可以是块
NSNumber* (^lookUpSeason)(NSString *) = ^(NSString *seasonname){
static NSArray *seasons;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
seasons = @[@"spring", @"summer", @"fall", @"winter"];
});
return @([seasons indexOfObject:seasonname]);
};
乍一看可能有点笨重,但使用后可读性提高。
return [@([seasons indexOfObject:string1Comps[1]]) compare:@([seasons indexOfObject:string2Comps[1]])];
变成
return [lookUpSeason(string1Comps[1]) compare:lookUpSeason(string2Comps[1])];
在这两种情况下,您还可以将查找代码放入比较器块中,这将使您有机会在其他地方删除与查找相同的比较器。
赞:
NSArray *strings = @[@"2005 fall", @"2007 spring", @"2005 spring", @"2007 winter", @"2005 winter", @"2005 summer", @"2000 hhh"];
NSComparisonResult (^yearAndSeasonComparator)(id,id) = ^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSNumber* (^lookUpSeason)(NSString *) = ^(NSString *seasonname){
static NSArray *seasons;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
seasons = @[@"spring", @"summer", @"fall", @"winter"];
});
return @([seasons indexOfObject:seasonname]);
};
NSArray *string1Comps = [obj1 componentsSeparatedByString:@" "];
NSArray *string2Comps = [obj2 componentsSeparatedByString:@" "];
NSComparisonResult compareYearResult = [@([string1Comps[0] integerValue]) compare:@([string2Comps[0] integerValue]) ];
if (compareYearResult == NSOrderedSame) {
return [lookUpSeason(string1Comps[1]) compare:lookUpSeason(string2Comps[1])];
}
return compareYearResult;
};
strings = [strings sortedArrayUsingComparator:yearAndSeasonComparator];
分配给 yearAndSeasonComparator
的块现在可以在对类似字符串进行排序的其他地方重复使用。
我有一个表视图,它的 header 存储在一个可变数组中,数组看起来像
(2005 fall, 2005 spring, 2007 summer...)
当我输出tableview时,我想要header按时间升序显示。
2005 spring
2005 fall
2007 summer
我在这里使用了代码:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
[self.sectionKeys sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
NSString *key = [self.sectionKeys objectAtIndex:section];
return key;
}
与 year
配合使用效果很好。但是,由于字母原因,fall
出现在 spring
和 summer
之前,请问如何解决?
所以你有一个带有节键的数组。但是sections不是按照数组的顺序排列的,需要排序。您会注意到 cellForRowAtIndexPath: 需要完全相同的信息。所以在这个地方排序是错误的。
我如何处理这个问题:我有一个 属性 "unsortedSectionKeys" 和一个 属性 "sortedSectionKeys"。 sortedSectionKeys 有一个 getter 检查 nil 并存储 unsortedSectionKeys 的排序副本,如果它是 nil。每当 unsortedSectionKeys 发生变化时,您只需将 sortedSectionKeys 设置为 nil。 (这至少解决了一些问题)。
对于排序,您需要编写正确的代码。使用 (void)sortUsingComparator:(NSComparator)cmptr 对可变对象进行排序,或 - (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr 获取数组的排序副本。
示例:
[self.sectionKeys sortArrayUsingComparator:^NSComparisonResult(NSString* obj1, NSString* obj2) {
NSInteger year1 = obj1.integerValue;
NSInteger year2 = obj2.integerValue;
if (year1 < year2) return NSOrderedAscending;
if (year1 > year2) return NSOrderedDescending;
NSInteger season1 = 0;
if ([obj1 rangeOfString:@"spring" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 1;
if ([obj1 rangeOfString:@"summer" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 2;
if ([obj1 rangeOfString:@"fall" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 3;
if ([obj1 rangeOfString:@"winter" options:NSCaseInsensitiveSearch].location != NSNotFound)
season1 = 4;
NSInteger season2 = 0;
if ([obj2 rangeOfString:@"spring" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 1;
if ([obj2 rangeOfString:@"summer" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 2;
if ([obj2 rangeOfString:@"fall" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 3;
if ([obj2 rangeOfString:@"winter" options:NSCaseInsensitiveSearch].location != NSNotFound)
season2 = 4;
if (season1 < season2) return NSOrderedAscending;
if (season1 > season2) return NSOrderedDescending;
return NSOrderedSame;
}];
您决定冬天是一年中的第一个还是最后一个季节,因为通常是 12 月到 2 月。
使用自定义比较器获取自定义排序顺序:
NSMutableArray *array = [@[ @"2005 fall", @"2005 spring", @"2007 summer" ] mutableCopy];
NSArray *seasons = @[ @"spring", @"summer", @"fall", @"winter" ];
[array sortUsingComparator:^NSComparisonResult(NSString *str1, NSString *str2) {
NSArray *parts1 = [str1 componentsSeparatedByString:@" "];
NSArray *parts2 = [str1 componentsSeparatedByString:@" "];
NSString *year1 = parts1[0];
NSString *year2 = parts2[0];
NSComparisonResult yearRes = [year1 compare:year2 options:NSNumericSearch];
if (yearRes == NSOrderedSame) {
NSString *season1 = parts1[1];
NSString *season2 = parts2[1];
NSUInteger index1 = [seasons indexOfObject:season1];
NSUInteger index2 = [seasons indexOfObject:season2];
if (index1 < index2) {
return NSOrderedAscending;
} else if (index1 > index2) {
return NSOrderedDescending;
} else {
return NSOrderedSame;
}
} else {
return yearRes;
}
}];
注意 - 我可能把 NSOrderedAscending
和 NSOrderedDescending
倒过来了。如果同年季节的排序顺序相反,则交换它们。
您需要一种查找机制来定义季节的顺序
NSArray *seasons = @[@"spring", @"summer", @"fall", @"winter"];
NSArray *strings = @[@"2005 fall",@"2007 spring", @"2005 spring", @"2007 winter", @"2005 winter"];
strings = [strings sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSArray *string1Comps = [obj1 componentsSeparatedByString:@" "];
NSArray *string2Comps = [obj2 componentsSeparatedByString:@" "];
NSComparisonResult compareYearResult = [@([string1Comps[0] integerValue]) compare:@([string2Comps[0] integerValue]) ];
if (compareYearResult == NSOrderedSame) {
return [@([seasons indexOfObject:string1Comps[1]]) compare:@([seasons indexOfObject:string2Comps[1]])];
}
return compareYearResult;
}];
结果
(
2005 spring,
2005 fall,
2005 winter,
2007 spring,
2007 winter
)
另一种查找机制可以是块
NSNumber* (^lookUpSeason)(NSString *) = ^(NSString *seasonname){
static NSArray *seasons;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
seasons = @[@"spring", @"summer", @"fall", @"winter"];
});
return @([seasons indexOfObject:seasonname]);
};
乍一看可能有点笨重,但使用后可读性提高。
return [@([seasons indexOfObject:string1Comps[1]]) compare:@([seasons indexOfObject:string2Comps[1]])];
变成
return [lookUpSeason(string1Comps[1]) compare:lookUpSeason(string2Comps[1])];
在这两种情况下,您还可以将查找代码放入比较器块中,这将使您有机会在其他地方删除与查找相同的比较器。
赞:
NSArray *strings = @[@"2005 fall", @"2007 spring", @"2005 spring", @"2007 winter", @"2005 winter", @"2005 summer", @"2000 hhh"];
NSComparisonResult (^yearAndSeasonComparator)(id,id) = ^NSComparisonResult(NSString *obj1, NSString *obj2) {
NSNumber* (^lookUpSeason)(NSString *) = ^(NSString *seasonname){
static NSArray *seasons;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
seasons = @[@"spring", @"summer", @"fall", @"winter"];
});
return @([seasons indexOfObject:seasonname]);
};
NSArray *string1Comps = [obj1 componentsSeparatedByString:@" "];
NSArray *string2Comps = [obj2 componentsSeparatedByString:@" "];
NSComparisonResult compareYearResult = [@([string1Comps[0] integerValue]) compare:@([string2Comps[0] integerValue]) ];
if (compareYearResult == NSOrderedSame) {
return [lookUpSeason(string1Comps[1]) compare:lookUpSeason(string2Comps[1])];
}
return compareYearResult;
};
strings = [strings sortedArrayUsingComparator:yearAndSeasonComparator];
分配给 yearAndSeasonComparator
的块现在可以在对类似字符串进行排序的其他地方重复使用。