Замена чисел в NSString объектами из NSArray - PullRequest
0 голосов
/ 06 июля 2011

В UITextView пользователи могут вводить числа, отформатированные как {{1}} или {{177}}.В поле предварительного просмотра, как здесь, в SO, я бы хотел заменить этот шаблон значением из NSArray, где число соответствует строке в массиве.

У меня есть две идеи, чтобы решить эту проблему:

  1. Подсчет всех вхождений с помощью выражения NSRegularExpoop, их цикл и замена их.
  2. Создание массива слов из строки NSSt и цикл по массиву, замена вхождений и помещение строки NSString.вместе.

Какой из этих двух вариантов является более производительным и надежным?Есть ли другой способ?

- обновление - Это регулярное выражение для поиска шаблона: @"\\{\\{([1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\}\\}".Как я могу использовать это в цикле с целым числом, чтобы заменить шаблон?

Ответы [ 3 ]

2 голосов
/ 06 июля 2011

Вот ответы, использующие NSRegularExpression:

NSString * input = @"{{83}} fjsdkfjds {{122}}";

NSMutableString * strToMakeReplacements = [[NSMutableString alloc] initWithString:input];

NSError * error = nil;
NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern:@"\\{\\{([1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\}\\}" options:NSRegularExpressionCaseInsensitive    error:&error];

NSArray * matches = [regex matchesInString:input options:NSMatchingReportProgress range:NSMakeRange(0, [input length])];

for (int i = [matches count]-1; i>=0 ; i--) {
    NSTextCheckingResult * match = [matches objectAtIndex:i];

    NSRange matchRange = match.range;
    NSString * numString = [input substringWithRange:NSMakeRange(matchRange.location+2, matchRange.length-4)];
    NSInteger num = [numString intValue];

    NSString * replacementValue = [self replacementValueForNum:num]; // write this function yourself

    [strToMakeReplacements replaceCharactersInRange:match.range withString:replacementValue];
}

Обратите внимание, что вам нужно избегать косых черт в вашем регулярном выражении, чтобы оно стало \\{\\{([1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\}\\}

1 голос
/ 06 июля 2011

A NSRegularExpression подход будет примерно таким -

NSRegularExpression * expression = [NSRegularExpression regularExpressionWithPattern:@"\\{\\{(\\d+?)\\}\\}"
                                                                             options:0
                                                                               error:nil];
NSMutableString * resultString = [aString mutableCopy];
NSTextCheckingResult * result;
NSUInteger location = 0;

/* Get the first match in the remaining string to search */
while ((result = [expression firstMatchInString:resultString options:0 range:NSMakeRange(location, [resultString length] - location)])) {

    /* Get the index of the array using the capture group 1 i.e. (\\d+?) */
    NSUInteger index = [[resultString substringWithRange:[result rangeAtIndex:1]] integerValue];

    /* Get the string that will replace the match */
    NSString * replacementString = [replacementStrings objectAtIndex:index];

    /* Replace the string */
    [resultString replaceCharactersInRange:result.range withString:replacementString];

    /* Skip to the end of the replaced string */
    location = result.range.location + [replacementString length];
}

Поскольку наши замещающие строки происходят из массива, я сомневаюсь, что у нас есть одно решение для этого. Здесь мы находим совпадение, заменяем его соответствующим образом и затем ищем совпадение в оставшейся части строки. Повторяем, результатов больше нет.

1 голос
/ 06 июля 2011

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

Учитывая входную строку NSString* input Я бы отфильтровал не числовыеследующие символы:

NSCharacterSet* notNumbersSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSArray * wholeNumbers = [input componentsSeparatedByCharactersInSet:notNumbersSet];

Теперь переберите массив целых чисел:

for( NSString* numString in wholeNumbers ) {
    NSInteger num = [numString intValue];
    // ...
}
...