正则表达式模式和/或NSRegularExpression搜索非常大的文件有点太慢,它可以优化吗?

Hal*_*lle 6 regex iphone objective-c openears nsregularexpression

在iOS框架中,我正在通过这个3.2 MB的文件搜索发音:https://cmusphinx.svn.sourceforge.net/svnroot/cmusphinx/trunk/pocketsphinx/model/lm/en_US/cmu07a.dic

我正在使用NSRegularExpression来搜索作为NSArray给出的任意一组单词.搜索是通过大文件的内容作为NSString完成的.我需要匹配换行符和制表符所包含的任何单词,然后抓住整行,例如,如果我在NSArray中有单词"monday",我想在字典文件中匹配这一行:

monday  M AH N D IY
Run Code Online (Sandbox Code Playgroud)

这一行以换行符开头,字符串"monday"后跟一个制表符,然后是发音.整个生产线需要与正则表达式匹配才能达到最终输出.我还需要找到列出的单词的替代发音,如下所示:

monday(2)   M AH N D EY
Run Code Online (Sandbox Code Playgroud)

替代发音始终以(2)开头,并且可以高达(5).因此,我还搜索单词的迭代,后跟括号,其中包含一个由换行符和制表符括起来的单个数字.

我有一个100%工作的NSRegularExpression方法如下:

NSArray *array = [NSArray arrayWithObjects:@"friday",@"monday",@"saturday",@"sunday", @"thursday",@"tuesday",@"wednesday",nil]; // This array could contain any arbitrary words but they will always be in alphabetical order by the time they get here.

// Use this string to build up the pattern.
NSMutableString *mutablePatternString = [[NSMutableString alloc]initWithString:@"^("]; 

int firstRound = 0;
for(NSString *word in array) {
    if(firstRound == 0) { // this is the first round

        firstRound++;
    } else { // After the first iteration we need an OR operator first.
        [mutablePatternString appendString:[NSString stringWithFormat:@"|"]];
     }
    [mutablePatternString appendString:[NSString stringWithFormat:@"(%@(\\(.\\)|))",word]];
}

[mutablePatternString appendString:@")\\t.*$"];

// This results in this regex pattern:

// ^((change(\(.\)|))|(friday(\(.\)|))|(monday(\(.\)|))|(saturday(\(.\)|))|(sunday(\(.\)|))|(thursday(\(.\)|))|(tuesday(\(.\)|))|(wednesday(\(.\)|)))\t.*$

NSRegularExpression * regularExpression = [NSRegularExpression regularExpressionWithPattern:mutablePatternString
                                                                                     options:NSRegularExpressionAnchorsMatchLines
                                                                                       error:nil];
int rangeLocation = 0;
int rangeLength = [string length];
NSMutableArray * matches = [NSMutableArray array];
[regularExpression enumerateMatchesInString:string
                                     options:0
                                       range:NSMakeRange(rangeLocation, rangeLength)
                                  usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop){
                                      [matches addObject:[string substringWithRange:result.range]];
                                  }];

[mutablePatternString release];

// matches array is returned to the caller.
Run Code Online (Sandbox Code Playgroud)

我的问题是,鉴于大文本文件,它在iPhone上的速度不够快.iPhone 4上的8个字需要1.3秒,这对应用来说太长了.鉴于以下已知因素:

•3.2 MB文本文件具有按字母顺序列出的匹配单词

•要查找的任意单词数组在使用此方法时始终按字母顺序排列

•替换发音以(2)在单词后面的parens开头,而不是(1)

•如果没有(2)则不会有(3),(4)或更多

•一种替代发音的存在很少见,平均每8次发生一次.进一步的替代发音甚至更罕见.

是否可以通过改进正则表达式或Objective-C的某些方面来优化此方法?我假设NSRegularExpression已经足够优化,不值得尝试使用不同的Objective-C库或在C中,但如果我错了,请告诉我.否则,非常感谢有关改善性能的任何建议.我希望,使这个推广到任何语音文件,所以我试图从如计算字母范围提前做更多的限制搜索解决方案望而却步.

****编辑****

以下是iPhone 4上2012年8月16日所有与搜索相关的答案的时间安排:

dasblinkenlight的创建NSDictionary方法/sf/answers/837119671/:5.259676

Ωmega在/sf/answers/837027481/上的最快正则表达式:0.609593秒

在dasblinkenlight的多个NSRegularExpression做法/sf/answers/837872171/:1.255130秒

我的第一个混合方法是/sf/answers/837938461/:0.372215

我的第二个混合方法在/sf/answers/837938461/:0.337549

到目前为止,最好的时间是我的答案的第二个版本.我不能最好地标记任何答案,因为所有与搜索相关的答案都告诉了我在我的版本中采用的方法,所以他们都非常有帮助,而我的只是基于其他人.我学到了很多,我的方法结束了原来时间的四分之一所以这是很大的帮助,谢谢dasblinkenlight和Ωmega通过与我说话的时候.

Ωme*_*ega 4

试试这个:

^(?:change|monday|tuesday|wednesday|thursday|friday|saturday|sunday)(?:\([2-5]\))?\t.*$
Run Code Online (Sandbox Code Playgroud)

还有这个(使用正向前瞻和可能的第一个字母列表):

^(?=[cmtwfs])(?:change|monday|tuesday|wednesday|thursday|friday|saturday|sunday)(?:\([2-5]\))?\t.*$
Run Code Online (Sandbox Code Playgroud)

最后是经过一些优化的版本:

^(?=[cmtwfs])(?:change|monday|t(?:uesday|hursday)|wednesday|friday|s(?:aturday|unday))(?:\([2-5]\))?\t.*$
Run Code Online (Sandbox Code Playgroud)