简体   繁体   English

对字符串的nsarray进行排序而不是基于字符串

[英]Sorting an nsarray of strings not string based

So i have an array that i retrieve from a web service in no particular order 所以我有一个数组,我从Web服务检索没有特定的顺序

example: 例:

0 => x large, 
1 => large, 
2 => XX large, 
3 => small,
4 => medium, 
5 => x small

I need to sort them: firstly based on specific - which could be reverse alphabetic: 我需要对它们进行排序:首先根据具体情况 - 可能是反向字母:

small
medium
large

Secondly i need to sort them based on their 'x' counter parts: 其次,我需要根据他们的'x'计数器部分对它们进行排序:

x small
small
medium
large
x large
xx large

I know i can do this with brute force string matching but i would really like a suggestion on how to do this tidily, perhaps a regex or something more elegant? 我知道我可以用蛮力字符串匹配来做到这一点,但我真的想要一个关于如何整齐地做这个的建议,也许是一个正则表达式或更优雅的东西?

Use NSComparator block syntax. 使用NSComparator块语法。 Something like 就像是

NSArray * sizes = [NSArray arrayWithObjects:  @"x small",@"small",@"medium",@"large",@"x large", nil];

NSArray *sortedBySizes =[array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    if ([sizes indexOfObject:[obj1 size]]> [sizes indexOfObject:[obj2 size]])
        return (NSComparisonResult)NSOrderedAscending;
    if ([sizes indexOfObject:[obj1 size]]< [sizes indexOfObject:[obj2 size]])
        return (NSComparisonResult)NSOrderedDescending;
    return (NSComparisonResult)NSOrderedSame;
}];

In the second approach I added a mapping between the numbers send by the web server and the x-sizes. 在第二种方法中,我添加了Web服务器发送的数字与x-sized之间的映射。 Now [obj size]; 现在[obj size]; is suppose to return a NSNumber object. 假设返回一个NSNumber对象。

NSArray * sizesStrings = [NSArray arrayWithObjects:  @"x small",@"small",
                                                     @"medium",@"large",
                                                     @"x large",@"xx large", 
                                                     nil];
NSArray * sizesNumbers = [NSArray arrayWithObjects:[NSNumber numberWithInt:5],
                                                   [NSNumber numberWithInt:3],
                                                   [NSNumber numberWithInt:4],
                                                   [NSNumber numberWithInt:1],
                                                   [NSNumber numberWithInt:0],
                                                   [NSNumber numberWithInt:2], 
                                                   nil];

NSDictionary *sizes = [NSDictionary dictionaryWithObjects:sizesStrings 
                                                   forKeys:sizesNumbers];

NSArray *sortedBySizes = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSString *sizeObj1String = [sizes objectForKey:[obj1 size]];
    NSString *sizeObj2String = [sizes objectForKey:[obj1 size]];

    int i1 = [sizesStrings indexOfObject:sizeObj1String];
    int i2 = [sizesStrings indexOfObject:sizeObj2String];

    if (i1 > i2)
        return (NSComparisonResult)NSOrderedAscending;
    if (i2 > i1)
        return (NSComparisonResult)NSOrderedDescending;
    return (NSComparisonResult)NSOrderedSame;
}];

The second task of the question — the grouping into small, medium, large — could be done like this: 问题的第二个任务 - 分为小,中,大 - 可以这样做:

NSDictionary *groups = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:[NSMutableArray array],[NSMutableArray array],[NSMutableArray array], nil] 
                                    forKeys:[NSArray arrayWithObjects:@"small",@"medium",@"large",nil]
                        ];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    int i = [[obj size] intValue];
    if (i == 5 || i == 3) 
        [[groups objectForKey:@"small"] addObject:obj];
    else if (i == 2 || i == 0 || i == 1)
        [[groups objectForKey:@"large"] addObject:obj];
    else
        [[groups objectForKey:@"medium"] addObject:obj];

}];

First, add a category to NSString for sanity's sake 首先,为了理智而为NSString添加一个类别

@implementation NSString (NSStringContainsCategory)

- (BOOL)contains:(NSString*)string;
{
    if(IsEmpty(string)) {
        return NO;
    }

    NSRange range = [self rangeOfString:string options:NSCaseInsensitiveSearch];

    if (range.location != NSNotFound) {
        return YES;
    }

    return NO;
}

@end

Then, 然后,

NSMutableArray* sortMe = [NSMutableArray arrayWithArray:theArrayYouWantToSort];

NSComparator smlComparator = ^NSComparisonResult(id string1, id string2) {
    // 1 = small, 2 = medium, 3 = large        
    NSNumber* string1Number = [NSNumber numberWithInt:0];
    NSNumber* string2Number = [NSNumber numberWithInt:0];

    if([string1 contains:@"large"]) {
        string1Number = [NSNumber numberWithInt:3];
    } else if([string1 contains:@"medium"]) {
        string1Number = [NSNumber numberWithInt:2];
    } else if([string1 contains:@"small"]) {
        string1Number = [NSNumber numberWithInt:1];
    }

    if([string2 contains:@"large"]) {
        string2Number = [NSNumber numberWithInt:3];
    } else if([string2 contains:@"medium"]) {
        string2Number = [NSNumber numberWithInt:2];
    } else if([string2 contains:@"small"]) {
        string2Number = [NSNumber numberWithInt:1];
    }

    NSComparisonResult compareSml = [string1Number compare:string2Number];

    if(compareSml == 0) {
        // if they are the same size, just use normal string comparison to sort x xx xxx etc
        return [string1 compare:string2];
    }
    return compareSml;
};

[sortMe sortUsingComparator:smlComparator];

I wouldn't call it elegant, but it's the simplest answer I could think of. 我不会称之为优雅,但这是我能想到的最简单的答案。 You may want to reverse the ordering to suit your needs - just apply negative to comparison result. 您可能希望颠倒排序以满足您的需求 - 只需对比较结果应用否定。 Comment if this doesn't work out, and I'll give it another look. 评论如果这不成功,我会再看看。

maybe you can sort your strings where "xx s" was replaced by "z", "xs" was replaced by "v" and "xl" replaced with "b" and "xx l" with "a". 也许你可以对你的字符串进行排序,其中“xx s”被“z”代替,“xs”被“v”替换,“xl”被“b”替换,“xx l”被替换为“a”。 q q

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM