寻求手动解决方案。
假设:
NSString *text = @"{a {b c}} {d e}";
没有正则表达式的好解决方案
NSUInteger len = text.length;
unichar buffer[len + 1];
[text getCharacters:buffer range:NSMakeRange(0, len)];
NSMutableOrderedSet<NSValue *> *results = [NSMutableOrderedSet orderedSet];
NSInteger depth = 0;
NSUInteger location = NSNotFound;
for (NSUInteger i = 0; i < len; i++) {
if (buffer[i] == '{')
{
if (depth == 0)
location = i;
depth++;
}
else if (buffer[i] == '}')
{
depth--;
if (depth == 0)
[results addObject:[NSValue valueWithRange:NSMakeRange(location, i - location + 1)]];
}
}
return results;
正则表达式的丑陋解决方案
NSString *innerPattern = @"\\{[^{}]*\\}";
NSRegularExpression *innerBracketsRegExp = [NSRegularExpression regularExpressionWithPattern:innerPattern options:0 error:nil];
// getting deepest matches
NSArray<NSTextCheckingResult *> *deepestMatches = [innerBracketsRegExp matchesInString:text options:0 range:NSMakeRange(0, text.length)];
// stripping them from text
text = [text stringByReplacingOccurrencesOfString:innerPattern withString:@"" options:NSRegularExpressionSearch range:NSMakeRange(0, text.length)];
// getting new deepest matches
NSArray<NSTextCheckingResult *> *depth2Matches = [innerBracketsRegExp matchesInString:text options:0 range:NSMakeRange(0, text.length)];
// merging the matches of different depth
NSMutableOrderedSet<NSValue *> *results = [NSMutableOrderedSet orderedSet];
for (NSTextCheckingResult *cr in depth2Matches) {
[results addObject:[NSValue valueWithRange:cr.range]];
}
for (NSTextCheckingResult *cr in deepestMatches) {
__block BOOL merged = NO;
[results enumerateObjectsUsingBlock:^(NSValue * _Nonnull value, NSUInteger idx, BOOL * _Nonnull stop) {
if (merged)
[results replaceObjectAtIndex:idx withObject:[NSValue valueWithRange:NSMakeRange(value.rangeValue.location + cr.range.length, value.rangeValue.length)]];
else if (NSLocationInRange(cr.range.location, value.rangeValue))
{
[results replaceObjectAtIndex:idx withObject:[NSValue valueWithRange:NSMakeRange(value.rangeValue.location, value.rangeValue.length + cr.range.length)]];
merged = YES;
}
else if (cr.range.location < value.rangeValue.location)
{
[results insertObject:[NSValue valueWithRange:cr.range] atIndex:idx];
merged = YES;
}
}];
if (!merged)
[results addObject:[NSValue valueWithRange:cr.range]];
}
return results;