在 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
此行以换行符开头,字符串“monday”后跟一个制表符,然后是发音。整行需要由正则表达式匹配才能最终输出。我还需要找到以下列出的单词的替代发音:
monday(2) M AH N D EY
替代发音总是以 (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.
我的问题是,考虑到大文本文件,它在 iPhone 上的速度还不够快。在 iPhone 4 上 8 个单词需要 1.3 秒,这对于应用程序来说太长了。鉴于以下已知因素:
• 3.2 MB 的文本文件按字母顺序列出要匹配的单词
• 使用此方法时,要查找的任意单词数组始终按字母顺序排列
• 替代发音在单词后面的括号中以 (2) 开头,而不是 (1)
• 如果没有 (2),则不会有 (3)、(4) 或更多
• 一种替代发音的出现很少见,平均可能出现 8 次中的 1 次。更多的替代发音更加罕见。
可以通过改进正则表达式或 Objective-C 的某些方面来优化此方法吗?我假设 NSRegularExpression 已经足够优化,不值得尝试用不同的 Objective-C 库或 C 语言来做,但如果我在这里错了,请告诉我。否则,非常感谢任何关于提高性能的建议。我希望将其推广到任何发音文件,因此我试图远离解决方案,例如提前计算字母范围以进行更多受限搜索。
****编辑****
以下是 2012 年 8 月 16 日给出的所有与搜索相关的答案在 iPhone 4 上的时间安排:
dasblinkenlight 的创建 NSDictionary 方法https://stackoverflow.com/a/11958852/119717 : 5.259676 秒
Ωmega 在https://stackoverflow.com/a/11957535/119717上最快的正则表达式:0.609593 秒
dasblinkenlight 在https://stackoverflow.com/a/11969602/119717的多个 NSRegularExpression 方法:1.255130 秒
我在https://stackoverflow.com/a/11970549/119717的第一个混合方法:0.372215 秒
我在https://stackoverflow.com/a/11970549/119717的第二种混合方法:0.337549 秒
迄今为止最好的时间是我答案的第二个版本。我无法将任何答案标记为最佳,因为所有与搜索相关的答案都告知了我在我的版本中采用的方法,因此它们都非常有用,而我的答案只是基于其他答案。我学到了很多东西,我的方法结束了原来的四分之一,所以这非常有帮助,感谢 dasblinkenlight 和 Ωmega 与我讨论。