2012-07-08 70 views
2

我正在使用NSScanner在大NSString中查找单词数组,然后使用html标记高亮显示它们。基本上我扫描到第一个单词并在该点插入标签。问题在于NSScanner也在查找单词的部分内容。 例如:NSScanner搜索单词找到单词的部分

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

TEST 测试 更高 试图

是否有一个很好的方法来设置NSScanner仅全字匹配? 谢谢。

+2

我想你会更好地使用正则表达式来解决这个问题。 – borrrden 2012-07-08 01:38:29

+0

Regex FTW !!!!!! – doNotCheckMyBlog 2012-07-08 01:39:28

+0

但如果我有一个问题,只能通过正则表达式解决...不,我现在有两个问题? ;) – shoe 2012-07-08 01:41:00

回答

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

枚举时不会修改吗?用这个函数做这件事是否安全? – borrrden 2012-07-08 02:19:03

+0

“如果将此方法发送给NSMutableString的实例,则只要它位于enclosingRange范围内,就允许进行变异(删除,添加或更改)。” – Wevah 2012-07-08 02:20:34

+0

忽略我,文档说它是好的:-X – borrrden 2012-07-08 02:20:35

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的
    • 测试三= 22毫秒
  2. W EVAH的解决方案
    • 测试一个= 249ms
    • 检验双= 189ms
    • 测试三= 295ms
  3. 我正则表达式解决上述
    • 测试一个= 69ms
    • 检验双= 34ms
    • 测试三= 26ms

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