3

我正在使用 NSScanner 在大型 NSString 中查找单词数组,然后使用 html 标签突出显示它们。基本上我扫描到第一个单词并在该点插入一个标签。问题是 NSScanner 也在寻找单词的一部分。例如:

如果我扫描@“test”,@“high”,@“try”,它将匹配许多单词的部分。

测试 测试 更高的尝试

有没有设置 NSScanner 只匹配整个单词的好方法?谢谢。

4

2 回答 2

1

首先感谢 Wevah 提供的 enumerateSubstrings 解决方案,它肯定是一个正确的解决方案。但是,它的性能不如我的解决方案所需的那样。我目前对这个问题的解决方案是根据 borrrden 的建议使用正则表达式(好的建议,谢谢)。我在时间分析器工具中分析了所有三个解决方案。

这是我目前的实现。

-(NSString *)getHighlightedString: (NSString *)unhighlightedString: (NSArray *)termsToHighlight
{

  NSMutableString *newString = [[NSMutableString alloc] initWithString:unhighlightedString];
  NSString *startTag = @"<b><i>";
  NSString *endTag = @"</i></b>";

  NSMutableString *expression = [[NSMutableString alloc] init];
  for (int i =0; i < [termsToHighlight count]; i++) 
  {
       [expression appendString:@"\\b"];
       [expression appendString:[termsToHighlight objectAtIndex:i]];
       [expression appendString:@"\\b"];

       if ([termsToHighlight count] != i + 1)
       {
           [expression appendString:@"|"];
       }

   }
   NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:expression options:NSRegularExpressionCaseInsensitive error:nil];
   NSArray* results = [regex matchesInString:unhighlightedString options:0 range:NSMakeRange(0, [unhighlightedString length])];
   for (NSTextCheckingResult* result in [results reverseObjectEnumerator]) {

       [newString insertString:endTag atIndex:result.range.location+result.range.length];
       [newString insertString:startTag atIndex:result.range.location];
   }

   return newString;
}

以下是三种不同测试中每种测试的性能:

  1. 我原来的 NSScanner 解决方案
    • 测试一 = 14ms
    • 测试二 = 14ms
    • 测试三 = 22ms
  2. Wevah的解决方案
    • 测试一 = 249ms
    • 测试二 = 189ms
    • 测试三 = 295ms
  3. 我上面的正则表达式解决方案
    • 测试一 = 69ms
    • 测试二 = 34ms
    • 测试三 = 26ms

所以你可以看到 nsscanner 很快,只是在这种情况下不够准确。我愿意放弃正则表达式对性能的小幅影响以获得准确性。

于 2012-07-08T14:34:52.067 回答
1

如果您的目标是 iOS 4 或更高版本,请查看-enumerateSubstringsInRange:options:usingBlock:

NSMutableString *string = [NSMutableString stringWithString:@"test this out testers! higher than high. try, trying, tryst."];
NSString *startTag = @"<b>";
NSString *endTag = @"</b>";
NSSet *wordsToMatch = [NSSet setWithObjects:@"test", @"high", @"try", nil];
[string enumerateSubstringsInRange:(NSRange){ .location = 0, .length = [string length] } options:NSStringEnumerationByWords usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    if ([wordsToMatch containsObject:substring]) {
        [string insertString:startTag atIndex:substringRange.location];
        [string insertString:endTag atIndex:substringRange.location + substringRange.length + startTag.length];
    }
}];
于 2012-07-08T02:15:28.687 回答