Сопоставьте имена, диалоги и действия из стенограммы с помощью регулярных выражений - PullRequest
0 голосов
/ 24 декабря 2018

Учитывая строковый диалог, такой как ниже, мне нужно найти предложение, соответствующее каждому пользователю.

text = 'CHRIS: Hello, how are you...
PETER: Great, you? PAM: He is resting.
[PAM SHOWS THE COUCH]
[PETER IS NODDING HIS HEAD]
CHRIS: Are you ok?'

В приведенном выше диалоге я хотел бы вернуть кортежи с тремя элементами:

  1. Имя человека

  2. Предложение в нижнем регистре и

  3. Предложения в скобках

Примерно так:

('CHRIS', 'Hello, how are you...', None)

('PETER', 'Great, you?', None)

('PAM', 'He is resting', 'PAM SHOWS THE COUCH. PETER IS NODDING HIS HEAD')

('CHRIS', 'Are you ok?', None)

etc...

Я пытаюсь использовать регулярные выражения для достижения вышеизложенного.До сих пор я смог получить имена пользователей с помощью приведенного ниже кода.Я изо всех сил пытаюсь определить предложение между двумя пользователями.

actors = re.findall(r'\w+(?=\s*:[^/])',text)

Ответы [ 2 ]

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

Regex - это один из способов решения этой проблемы, но вы также можете думать об этом как об повторении каждого токена в вашем тексте и применении некоторой логики для формирования групп.

Например, сначала мы могли бы найти группы имен и текста:

from itertools import groupby

def isName(word):
    # Names end with ':'
    return word.endswith(":")

text_split = [
    " ".join(list(g)).rstrip(":") 
    for i, g in groupby(text.replace("]", "] ").split(), isName)
]
print(text_split)
#['CHRIS',
# 'Hello, how are you...',
# 'PETER',
# 'Great, you?',
# 'PAM',
# 'He is resting. [PAM SHOWS THE COUCH] [PETER IS NODDING HIS HEAD]',
# 'CHRIS',
# 'Are you ok?']

Затем вы можете собрать пары последовательных элементов в text_split в кортежи:

print([(text_split[i*2], text_split[i*2+1]) for i in range(len(text_split)//2)])
#[('CHRIS', 'Hello, how are you...'),
# ('PETER', 'Great, you?'),
# ('PAM', 'He is resting. [PAM SHOWS THE COUCH] [PETER IS NODDING HIS HEAD]'),
# ('CHRIS', 'Are you ok?')]

Мы почти на желаемом выходе.Нам просто нужно разобраться с текстом в квадратных скобках.Вы можете написать простую функцию для этого.(Регулярные выражения здесь допустимы, но я намеренно избегаю этого в этом ответе.)

Вот что-то быстрое, что я придумал:

def isClosingBracket(word):
    return word.endswith("]")

def processWords(words):
    if "[" not in words:
        return [words, None]
    else:
        return [
            " ".join(g).replace("]", ".") 
            for i, g in groupby(map(str.strip, words.split("[")), isClosingBracket)
        ]

print(
    [(text_split[i*2], *processWords(text_split[i*2+1])) for i in range(len(text_split)//2)]
)
#[('CHRIS', 'Hello, how are you...', None),
# ('PETER', 'Great, you?', None),
# ('PAM', 'He is resting.', 'PAM SHOWS THE COUCH. PETER IS NODDING HIS HEAD.'),
# ('CHRIS', 'Are you ok?', None)]

Обратите внимание, что с помощью * для распаковки результата processWords в tuple - это строго функция Python 3.

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

Вы можете сделать это с помощью re.findall:

>>> re.findall(r'\b(\S+):([^:\[\]]+?)\n?(\[[^:]+?\]\n?)?(?=\b\S+:|$)', text)
[('CHRIS', ' Hello, how are you...', ''),
 ('PETER', ' Great, you? ', ''),
 ('PAM',
  ' He is resting.',
  '[PAM SHOWS THE COUCH]\n[PETER IS NODDING HIS HEAD]\n'),
 ('CHRIS', ' Are you ok?', '')]

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

Распределение регулярных выражений

\b              # Word boundary
(\S+)           # First capture group, string of characters not having a space
:               # Colon
(               # Second capture group
    [^          # Match anything that is not...
        :       #     a colon
        \[\]    #     or square braces
    ]+?         # Non-greedy match
)
\n?             # Optional newline
(               # Third capture group
    \[          # Literal opening brace
    [^:]+?      # Similar to above - exclude colon from match
    \] 
    \n?         # Optional newlines
)?              # Third capture group is optional
(?=             # Lookahead for... 
    \b          #     a word boundary, followed by  
    \S+         #     one or more non-space chars, and
    :           #     a colon
    |           # Or,
    $           # EOL
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...