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

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

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)

и как это будет для: ПЕТР КИВАТЬ ГОЛОВОЙ?

andreihondrari 24.12.2018 16:18

Это не обязательно похоже на проблему с регулярным выражением. Вы пробовали str.split? Также в выходных данных вашего примера, что случилось с "Are you ok?"?

pault 24.12.2018 16:24

@pault Я попытался разделить его на ':', но снова мне нужно идентифицировать первое слово перед ':' и все предложение после ':'. Предложение должно остановиться перед именем следующего пользователя. Вот почему я подумал, что регулярное выражение будет полезно. Также добавлено последнее предложение. Спасибо

pbou 24.12.2018 16:26

Я бы посмотрел в nltk и перестал писать собственное регулярное выражение. Спасибо за 2 года :)

Ufos 05.06.2019 18:06
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
6
4
1 236
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете сделать это с помощью 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?', '')]

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

Regex Breakdown

\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
)

Ого, результат выглядит именно так, как я искал. Для квадратных скобок у меня это есть, на всякий случай кому-нибудь понадобится. re.sub (r '([|])', '', текст). Спасибо

pbou 24.12.2018 16:31

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

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

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.

Спасибо тебе за это. Похоже, у меня есть случаи, когда между ']' и именем пользователя нет пробела. Следовательно, word.endswith (':') неправильно разделяет имя. ты знаешь, как я мог с этим справиться?

pbou 25.12.2018 11:05

@pbou один из способов - вначале заменить все "]" на "] ". Смотрите редактирование.

pault 26.12.2018 17:08

Другие вопросы по теме