使用两个特殊键对NSmutablearray进行排序

时间:2015-04-24 15:24:25

标签: objective-c sorting nsmutablearray

我有一个tableview,它的标题存储在mutablearray中,数组看起来像

(2005 fall, 2005 spring, 2007 summer...)

当我输出tableview时,我希望标题及时升序显示。

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出现在springsummer之前,因为字母统计,请该怎么做才能解决它?

3 个答案:

答案 0 :(得分: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;
    }
}];

注意 - 我可能会向后NSOrderedAscendingNSOrderedDescending。如果同一年的季节以相反的顺序出现,则交换它们。

答案 1 :(得分:2)

您需要一种查找机制来定义季节的顺序

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的块现在可以在其他可以对类似字符串进行排序的地方重复使用。

答案 2 :(得分:0)

所以你有一个带分区键的数组。但是这些部分不是数组的顺序,它们需要进行排序。您会注意到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月。