Найти неупорядоченные слова с RegEx - PullRequest
0 голосов
/ 23 декабря 2018

Я хочу использовать RegEx, чтобы найти первую последовательность в строке, где появляется набор слов, в любом порядке.

Например, при поиске слов hello, my и world, затем:

  • для hello my sweet world выражение будет соответствовать hello my sweet world;
  • для oh my, hello world оно будет соответствовать my, hello world;
  • дляoh my world, hello world это будет соответствовать my world, hello;
  • для hello world совпадения не будет.

После некоторых исследований я попробовал выражение (?=.*?\bhello\b)(?=.*?\bmy\b)(?=.*?\bworld\b).*, которое не соответствуетрешить мою проблему, так как она соответствует всей строке, если присутствуют все слова, например:

  • для oh my world, hello world соответствует oh my world, hello world

Что бысоответствующее выражение для достижения того, что я описал?

(Хотя RegEx является предпочтительным методом для моей программы, если вы считаете, что это не тот путь, любое другое решение на python приветствуется.)

Ответы [ 2 ]

0 голосов
/ 23 декабря 2018

Унифицированный итеративный питонический подход с использованием Pattern.finditer () и Set объекта:

import re

test_str = '''The introduction here for our novel. 
Oh, hello my friend. This world is full of beauty and mystery, let's say hello to universe ...'''

words_set = {'my', 'hello', 'world'}    # a set of search words
words_set_copy = set(words_set)
pat = re.compile(r'\b(my|hello|world)\b', re.I)
start_pos = None
first_sequence = ''

for m in pat.finditer(test_str):        
    if start_pos is None:
        start_pos = m.start()           # start position of the 1st match object
    words_set_copy.discard(m.group())   # discard found unique match 

    if not words_set_copy:              # all the search words found
        first_sequence += test_str[start_pos: m.end()]
        break

print(first_sequence)

Выход:

hello my friend. This world

Вы можете преобразовать вышеуказанный подход в функцию, чтобы сделать его многократно используемым.

0 голосов
/ 23 декабря 2018

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

\b(hello|my|world)\b.*?((?!\1)\b(?:hello|my|world)\b).*?(?:(?!\1)(?!\2)\b(?:hello|my|world)\b)

Идея здесь такова:

  1. Создайте группу чередования \b(hello|my|world)\b и поместите ее в group1
  2. Затем, при желании, после нее может быть ноль или более любых символов.
  3. Затем за ней должен следовать любой изоставшиеся два слова, а не то, которое было найдено в первой группе, поэтому я использовал ((?!\1)\b(?:hello|my|world)\b), и это второе совпадение затем помещается в группу 2.
  4. С другой стороны, он может иметь произвольно ноль или более любых символовследуя за ним.
  5. Затем мы снова применяем ту же логику, где третье слово должно быть тем, которое не было захвачено ни в группе 1, ни в группе 2, поэтому это регулярное выражение (?:(?!\1)(?!\2)\b(?:hello|my|world)\b)

Вот демоверсия

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...