Учитывая строковый диалог, как показано ниже, мне нужно найти предложение, соответствующее каждому пользователю.
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?'
Для приведенного выше диалога я хотел бы вернуть кортежи с тремя элементами:
Имя человека
Предложение в нижнем регистре и
Предложения в скобках
Что-то вроде этого:
('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)
Это не обязательно похоже на проблему с регулярным выражением. Вы пробовали str.split? Также в выходных данных вашего примера, что случилось с "Are you ok?"?
@pault Я попытался разделить его на ':', но снова мне нужно идентифицировать первое слово перед ':' и все предложение после ':'. Предложение должно остановиться перед именем следующего пользователя. Вот почему я подумал, что регулярное выражение будет полезно. Также добавлено последнее предложение. Спасибо
Я бы посмотрел в nltk и перестал писать собственное регулярное выражение. Спасибо за 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 '([|])', '', текст). Спасибо
Регулярное выражение - это один из способов решения этой проблемы, но вы также можете рассматривать его как итерацию по каждому токену в вашем тексте и применение некоторой логики для формирования групп.
Например, мы могли сначала найти группы имен и текста:
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 один из способов - вначале заменить все "]" на "] ". Смотрите редактирование.
и как это будет для: ПЕТР КИВАТЬ ГОЛОВОЙ?