В среде iOS я ищу произношение в этом файле размером 3,2 МБ: https://cmusphinx.svn.sourceforge.net/svnroot/cmusphinx/trunk/pocketsphinx/model/lm/en_US/cmu07a.dic
Я использую NSRegularExpression для поиска произвольного набора слов, которые заданы как NSArray. Поиск осуществляется по содержимому большого файла в виде NSString. Мне нужно сопоставить любое слово, которое появляется в квадратных скобках с помощью новой строки и символа табуляции, а затем взять всю строку, например, если у меня есть слово «понедельник» в моем NSArray, я хочу сопоставить эту строку в файле словаря:
monday M AH N D IY
Эта строка начинается с новой строки, за строкой «понедельник» следует символ табуляции, а затем следует произношение. Вся строка должна быть сопоставлена с регулярным выражением для ее окончательного вывода. Мне также нужно найти альтернативные варианты произношения слов, перечисленных ниже:
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. 8 слов занимают 1,3 секунды на iPhone 4, что слишком долго для приложения. Учитывая следующие известные факторы:
• В текстовом файле размером 3,2 МБ слова для соответствия перечислены в алфавитном порядке.
• Массив произвольных слов для поиска всегда находится в алфавитном порядке, когда они попадают в этот метод.
• Альтернативное произношение начинается с (2) в скобках после слова, а не (1)
• Если нет (2), не будет (3), (4) или более
• Наличие одного альтернативного произношения встречается редко, в среднем 1 раз из 8. Дальнейшее альтернативное произношение встречается еще реже.
Можно ли оптимизировать этот метод, улучшив регулярное выражение или какой-либо аспект Objective-C? Я предполагаю, что NSRegularExpression уже достаточно оптимизирован, поэтому не стоит пытаться сделать это с другой библиотекой Objective-C или в C, но если я ошибаюсь, дайте мне знать. В противном случае, очень благодарен за любые предложения по улучшению производительности. Я надеюсь сделать это обобщенным для любого файла произношения, поэтому я стараюсь держаться подальше от таких решений, как расчет алфавитных диапазонов заранее, чтобы выполнять более ограниченный поиск.
****РЕДАКТИРОВАТЬ****
Вот время на iPhone 4 для всех связанных с поиском ответов, данных до 16 августа 2012 года:
подход dasblinkenlight к созданию NSDictionary https://stackoverflow.com/a/11958852/119717: 5,259676 секунд
Самое быстрое регулярное выражение Ωmega на https://stackoverflow.com/a/11957535/119717: 0,609593 секунды
подход dasblinkenlight с несколькими NSRegularExpression в https://stackoverflow.com/a/11969602/119717: 1,255130 секунд
мой первый гибридный подход на https://stackoverflow.com/a/11970549/119717: 0,372215 секунд
мой второй гибридный подход на https://stackoverflow.com/a/11970549/119717: 0,337549 секунд
Лучшее время пока - вторая версия моего ответа. Я не могу отметить ни один из ответов как лучший, поскольку все ответы, связанные с поиском, сообщают о подходе, который я использовал в своей версии, поэтому все они очень полезны, а мой просто основан на других. Я многому научился, и мой метод закончился в четверть первоначального времени, так что это было чрезвычайно полезно, спасибо dasblinkenlight и Ωmega за обсуждение этого со мной.
^(sunday|monday|tuesday|...)(\t|\\().*$
: вы знаете, что все, что входит в круглые скобки, представляет собой одиночный символ, за которым следует закрывающая круглая скобка, поэтому вы можете пропустить эту часть соответствовать. Объединение всех ваших строк в один блокOR
также может помочь, но я не уверен, что это сильно поможет. - person Sergey Kalinichenko   schedule 14.08.2012