3

私は NSScanner を使用して、大きな NSString 内の単語の配列を探し、それらを html タグで強調表示しています。基本的に、最初の単語までスキャンして、その時点でタグを挿入します。問題は、NSScanner が単語の一部も検出していることです。例えば:

@"test"、@"high"、@"try" をスキャンすると、多くの単語の一部に一致します。

TEST TESTING HIGHHer TRYing

単語全体にのみ一致するように NSScanner を設定する良い方法はありますか? ありがとう。

4

2 に答える 2

1

まず、enumerateSubstrings を使用したソリューションについて Wevah に感謝します。これは確かに正しいソリューションです。ただし、ソリューションに必要なほどパフォーマンスは高くありません。この問題に対する私の現在の解決策は、borrrden による提案に基づいて正規表現を使用することです (良い提案、ありがとう)。そして、タイム プロファイラー ツールで 3 つのソリューションすべてをプロファイリングしました。

これが私の現在の実装です。

-(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;
}

3 つの異なるテストのそれぞれのパフォーマンスは次のとおりです。

  1. 私のオリジナルの NSScanner ソリューション
    • テスト 1 = 14ms
    • テスト 2 = 14ms
    • テスト 3 = 22ms
  2. Wevah のソリューション
    • テスト 1 = 249ms
    • テスト 2 = 189ms
    • テスト 3 = 295ms
  3. 上記の私の正規表現ソリューション
    • テスト 1 = 69ms
    • テスト 2 = 34ms
    • テスト 3 = 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 に答える