Replacing numbers in an NSString with Objects from NSArray
In a UITextView users can enter numbers formatted like {{1}}
or {{177}}
. In a preview field, much like here on SO I'd like to replace that pattern with a value from an NSArray, where the number corresponds to the row in the array.
I have two ideas to solve this:
- Count all occurrences with an NSRegularExpression, loop through them and replace them.
- Create a word-array out of the NSString and loop through the array, replacing occurrences and put the NSString back together.
Which of those two options is more performant and reliable? Is开发者_StackOverflow社区 there another way?
-- update --
This is the regular expression to find the pattern: @"\\{\\{([1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\}\\}"
. How can I use this in a loop with an integer to replace the pattern?
Here's an answers using 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];
}
Note that you need to escape the slashes in your regex, so that it becomes \\{\\{([1-9]|[1-9][0-9]|[1-9][0-9][0-9])\\}\\}
I would use the second approach since it seems more convenient than using regular expressions (although I'm admittedly not very experienced with them).
Given an input string NSString* input
I would filter out not numeric characters as follows:
NSCharacterSet* notNumbersSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSArray * wholeNumbers = [input componentsSeparatedByCharactersInSet:notNumbersSet];
Now loop through the array of whole numbers:
for( NSString* numString in wholeNumbers ) {
NSInteger num = [numString intValue];
// ...
}
A NSRegularExpression
approach would be something like this –
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];
}
Since our replacement strings come from an array I doubt we have a single statement solution to this. Here we find a match, replace it appropriately and then search the rest of the string for a match. We repeat this there are no more results.
精彩评论