Сортировка nsarray строк не на основе строк - PullRequest
5 голосов
/ 29 ноября 2011

Итак, у меня есть массив, который я извлекаю из веб-службы в произвольном порядке

пример:

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

Мне нужно отсортировать их: сначала на основе конкретных - которые могут быть обратными буквенными:

small
medium
large

Во-вторых, мне нужно отсортировать их по их встречным частям 'x':

x small
small
medium
large
x large
xx large

Я знаю, что могу сделать это с помощью сопоставления строк методом грубой силы, но мне бы очень хотелось, чтобы предложение о том, как сделать это аккуратно, возможно, регулярное выражение или что-то более элегантное?

Ответы [ 3 ]

10 голосов
/ 29 ноября 2011

Использовать NSComparator блочный синтаксис. Что-то вроде

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;
}];

Во втором подходе я добавил отображение между числами, отправляемыми веб-сервером, и размерами x. Теперь [obj size]; предполагается вернуть объект 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;
}];

Второе задание вопроса - группировка по малому, среднему, крупному - можно сделать так:

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];

}];
3 голосов
/ 29 ноября 2011

Сначала добавьте категорию в 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

Тогда

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];

Я бы не назвал это элегантным, но это самый простой ответ, который я мог придумать. Вы можете изменить порядок в соответствии с вашими потребностями - просто примените отрицательный результат сравнения. Прокомментируйте, если это не сработает, и я еще раз посмотрю.

0 голосов
/ 29 ноября 2011

возможно, вы можете отсортировать строки, где «xx s» был заменен на «z», «xs» был заменен на «v», а «xl» заменен на «b» и «xx l» на «a».д

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...