Регулярное выражение со списком «включить» и списком «исключить»

У меня есть предложение (слова, разделенные пробелами).

Затем у меня есть два списка фраз (полные или частичные слова, т. е. не содержащие пробелов): один — список «включить», а другой — список «исключить».

Соответствующее предложение будет содержать все фразы из списка «включить» (перекрытия допустимы, регистр не учитывается) и ни одну фразу из списка «исключить».

Как проверить, соответствует ли предложение правилам? Спасибо.

Пример

Предложение = This yammy Flybe catalog is sticky

Включить список = cat fly tic

Список исключений = veg pot yam

Тест не пройден, потому что, несмотря на то, что в предложении присутствуют все фразы «включить», одна из фраз «исключить» (yam) все же присутствует. Измените слово yammy на yummy, и тест должен пройти.

P.S. в настоящее время для этого используется реализация разделения отношений в SQL, которая кажется хорошо оптимизированной, когда данные уже находятся в базе данных SQL. Теперь у меня есть структура данных, поступающая из внешнего источника. Я полагаю, что мог бы передать строки с разделителями, разделить на строки таблицы и т. д., но я хочу изучить другие варианты. Итак, если не регулярное выражение, то что?


person metaopoly    schedule 10.12.2009    source источник
comment
Я предлагаю для добавленного нового вопроса открыть отдельный вопрос (убедитесь, что он не слишком похож на дубликат), где вы явно запрашиваете другие подходы, чем тот, который представлен в этой теме. Маловероятно, что люди найдут новые вопросы, добавленные во время редактирования... Кстати, ваш пример превосходен и работает с предложенным решением.   -  person Abel    schedule 10.12.2009


Ответы (1)


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

^(?=.*include1)(?=.*include2)(?=.*...)(?!.*(?:exclude1|exclude2|...))

Обязательно используйте Regex.Escape в отдельных предложениях, прежде чем добавлять их в выражение включения или исключения. Регулярное выражение работает следующим образом:

  • Если в совпадающей строке есть include1, то это удается, если нет, то не удается и
  • Если в совпадающей строке есть include2, то это удается, если нет, то не удается и
  • Если в совпадающей строке есть includeX, то это удается, если нет, то не удается и
  • Если exclude1 находится в соответствующей строке, происходит сбой или
  • Если exclude2 находится в соответствующей строке, происходит сбой или
  • Если excludeX находится в соответствующей строке, происходит сбой.

Другими словами: все включаемые предложения должны быть в (в любом порядке), все исключающие предложения должны быть в отсутствующих.

Примечание: этот тип регулярных выражений, даже в скомпилированном виде, не очень хорошо оптимизируется механизмом регулярных выражений .NET. Если список включений/исключений становится большим, простая процедура конкатенации уже может быть очень дорогостоящей. Наконец, альтернатива (сопоставьте отдельные предложения одно за другим), возможно, еще медленнее. Чтобы выяснить это, измерьте производительность любого из подходов.

Обновление: исправлена ​​ошибка в коде и добавлено объяснение.

person Abel    schedule 10.12.2009
comment
Превосходно! Это должно применяться к каждому предложению, да? Любой способ расширить его, чтобы применить ко всей строке с разделителями табуляции, или это безумие? Спасибо. - person metaopoly; 10.12.2009
comment
Вы можете применить его к любой строке любой длины. Если вы хотите применить его к частям строки по отдельности (где к частям применяется полный набор правил), я предлагаю сначала разбить строку, а затем foreach по каждому элементу и применить регулярное выражение к каждому (не волнуйтесь , регулярное выражение будет кэшироваться .NET). Его можно настроить так, чтобы он работал для частей между вкладками, но тогда это становится очень сложным регулярным выражением, которое даже опытным пользователям регулярных выражений будет трудно понять. - person Abel; 10.12.2009
comment
Я заметил ошибку, но к тому времени, когда я опубликовал пример, вы ее исправили, молодец! Это регулярное выражение, которое я искал. Я уберу требование «вкладки», чтобы посмотреть, не появится ли что-нибудь еще, не зависящее от языка. - person metaopoly; 10.12.2009
comment
Приведенное выше регулярное выражение не зависит от языка в той степени, в которой любой язык, поддерживающий регулярные выражения, будет понимать это регулярное выражение при условии, что они поддерживают обход (Perl, PHP, Python, Java). - person Abel; 10.12.2009