2015-01-02 2 views
0

У меня есть регулярное выражение в C#, где шаблон 8000 + слова (или группа слов) каждый, разделенные границами слов, а именно:с вопросом # Regular скорости Expression

"\\bword1\\b|\\bword2 word3 word4\\b|.......etc" 

Я пытаюсь, чтобы соответствовать слова (или группы слов) в строке для любого слова (или группы слов) в этом выражении. Все работает отлично, но я обнаружил, что для завершения операции в среднем требуется 37 мс.

Интересно, что если я делаю то же самое, но используя String.IndexOf и некоторые запутанные методы, он работает значительно быстрее (но все же слишком медленный), который я нахожу странным.

Мне известны другие двигатели регулярных выражений, в частности re2/google, но я очень хочу использовать встроенные функции C#, где это возможно.

Если у кого-то есть совет, это будет оценено по достоинству.

+0

те \ Б имеют две косые черты в реальной жизни ... они только что избежали при отправке! –

+1

Вы использовали RegexOptions.Compiled? Tohugh 8000+ Word шаблон довольно перебор, я думаю. – CSharpie

+0

@james Вот почему в редакторе есть опция «формат как код». ;) – Tomalak

ответ

4

Чтобы понять, почему ваше регулярное выражение медленно, вы должны просто представить себе, как работают регулярные выражения.

В вашем случае (8000) альтернативы

  • Шаг 1. Начало входного символа 0.
  • Шаг 2. Попытка соответствовать альтернативным 0. К сожалению, нет соответствия.
  • Шаг 3. Попробуйте сопоставить альтернативу 1. Ой, нет совпадения.
  • ...
  • Шаг 4000. Попробуйте сопоставить альтернативу 4001. Yay! Матч первого персонажа!
  • Шаг 4001. Попробуйте сопоставить альтернативу 4001. Yay! Матч второго персонажа!
  • Шаг 4002. Попробуйте сопоставить альтернативную 4001. К сожалению, совпадений нет.
  • Шаг 4003. Постарайтесь сопоставить альтернативу 4002. К сожалению, нет совпадений.
  • ...
  • Шаг 8963. Попробуйте сопоставить альтернативу 7999. К сожалению, не соответствует.
  • Шаг 8964. Ошибка все альтернативы на входе символ 0.
  • Шаг 8965. Переход к символу ввода 1.
  • Шаг 8966. Попытка соответствовать альтернативных 0. К сожалению, нет соответствия.
  • ...

Чем длиннее строка ввода, тем больше альтернатив ваше регулярное выражение имеет и более «почти, но не совсем» матчи происходят во входной строке, тем медленнее это получит.

Если вы можете сделать это быстрее с String.IndexOf(), сделайте это. Вы никогда не будете делать это быстрее с регулярным выражением.

Исследуйте другие способы поиска строк для слов. Какой из них будет работать для вас, зависит от того, как выглядит ваш ввод.

+0

Спасибо, я буду продолжать искать пути ... очевидно, один способ уменьшить количество слов в регулярном выражении, но я изо всех сил пытаюсь это сделать в данный момент (длинная история) –

+0

Я думаю, что вы находитесь в точке, где регулярное выражение больше не стоит стратегии. – Tomalak

+0

Поверьте, это также можно назвать «Катастрофическим обратным следом» – David

0

Я бы предложил перейти на HashSet, потому что он кажется более подходящим для вашей задачи.

Вот проект того, что вы могли бы сделать:

// produce string[] containing your words 
var words = myRegexp.split("\\b|\\"); 

var mySet = new HashSet<string>(words); 
// usage 
mySet.Contains("find this");