Разделение строки на слова и пунктуацию
Я пытаюсь разбить строку на слова и пунктуацию, добавив пунктуацию в список, созданный разделом.
Например:
>>> c = "help, me"
>>> print c.split()
['help,', 'me']
Я хочу, чтобы список выглядел так:
['help', ',', 'me']
Итак, я хочу, чтобы строка была разделена на пробел с препинанием, разделенным на слова.
Я попытался сначала разобрать строку, а затем запустить split:
>>> for character in c:
... if character in ".,;!?":
... outputCharacter = " %s" % character
... else:
... outputCharacter = character
... separatedPunctuation += outputCharacter
>>> print separatedPunctuation
help , me
>>> print separatedPunctuation.split()
['help', ',', 'me']
Это дает результат, который я хочу, но очень тяжелый для больших файлов.
Есть ли способ сделать это более эффективно?
Ответы
Ответ 1
Это более или менее способ сделать это:
>>> import re
>>> re.findall(r"[\w']+|[.,!?;]", "Hello, I'm a string!")
['Hello', ',', "I'm", 'a', 'string', '!']
Трюк заключается в том, чтобы не думать о том, где разделить строку, но что включить в токены.
Предостережения:
- Подчеркивание (_) считается символом внутреннего слова. Замените \w, если вы этого не хотите.
- Это не будет работать с (одиночными) кавычками в строке.
- Поместите любые дополнительные знаки препинания, которые вы хотите использовать в правой половине регулярного выражения.
- Все, что явно не упоминается в re, тихо отбрасывается.
Ответ 2
Вот версия, поддерживающая Unicode:
re.findall(r"\w+|[^\w\s]", text, re.UNICODE)
Первый вариант улавливает последовательности словных символов (как определено в unicode, поэтому "резюме" не превратится в ['r', 'sum']
); второй ловит отдельные символы без слов, игнорируя пробелы.
Обратите внимание, что в отличие от верхнего ответа это рассматривает отдельную цитату как отдельную пунктуацию (например, "Я есть" → ['I', "'", 'm']
). Это кажется стандартным в NLP, поэтому я считаю его особенностью.
Ответ 3
В синтаксисе регулярных выражений в стиле perl \b
соответствует границе слова. Это должно пригодиться для выполнения разделения на основе регулярного выражения.
edit: мне сообщили, что "пустые совпадения" не работают в функции split модуля Python re. Я оставлю это здесь в качестве информации для тех, кто все еще сталкивается с этой "особенностью".
Ответ 4
Здесь моя запись.
У меня есть сомнения относительно того, насколько хорошо это будет задерживаться в смысле эффективности или если оно уловит все случаи (обратите внимание на "!!!", сгруппированные вместе, это может быть или не быть хорошо).
>>> import re
>>> import string
>>> s = "Helo, my name is Joe! and i live!!! in a button; factory:"
>>> l = [item for item in map(string.strip, re.split("(\W+)", s)) if len(item) > 0]
>>> l
['Helo', ',', 'my', 'name', 'is', 'Joe', '!', 'and', 'i', 'live', '!!!', 'in', 'a', 'button', ';', 'factory', ':']
>>>
Одна очевидная оптимизация заключается в том, чтобы скомпилировать регулярное выражение перед обработкой (используя re.compile), если вы будете делать это поэтапно.
Ответ 5
Здесь небольшое обновление вашей реализации. Если вы пытаетесь сделать что-то более подробное, я предлагаю изучить NLTK, предложенный le dorfier.
Это может быть только немного быстрее, так как вместо "+" используется .join(), который известен быстрее.
import string
d = "Hello, I'm a string!"
result = []
word = ''
for char in d:
if char not in string.whitespace:
if char not in string.ascii_letters + "'":
if word:
result.append(word)
result.append(char)
word = ''
else:
word = ''.join([word,char])
else:
if word:
result.append(word)
word = ''
print result
['Hello', ',', "I'm", 'a', 'string', '!']
Ответ 6
Я думаю, вы можете найти всю помощь, которую вы можете себе представить в NLTK, тем более, что вы используете python. Там хорошее всестороннее обсуждение этой проблемы в учебнике.
Ответ 7
Я придумал способ токенизировать все слова и шаблоны \W+
, используя \b
, который не требует жесткого кодирования:
>>> import re
>>> sentence = 'Hello, world!'
>>> tokens = [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', sentence)]
['Hello', ',', 'world', '!']
Здесь .*?\S.*?
- это шаблон, сопоставляющий все, что не является пространством, и $
добавляется в соответствие с последним токеном в строке, если это символ пунктуации.
Обратите внимание на следующее: это будет группировать знаки препинания, состоящие из более чем одного символа:
>>> print [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', '"Oh no", she said')]
['Oh', 'no', '",', 'she', 'said']
Конечно, вы можете найти и разбить такие группы:
>>> for token in [t.strip() for t in re.findall(r'\b.*?\S.*?(?:\b|$)', '"You can", she said')]:
... print re.findall(r'(?:\w+|\W)', token)
['You']
['can']
['"', ',']
['she']
['said']
Ответ 8
Попробуйте следующее:
string_big = "One of Python coolest features is the string format operator This operator is unique to strings"
my_list =[]
x = len(string_big)
poistion_ofspace = 0
while poistion_ofspace < x:
for i in range(poistion_ofspace,x):
if string_big[i] == ' ':
break
else:
continue
print string_big[poistion_ofspace:(i+1)]
my_list.append(string_big[poistion_ofspace:(i+1)])
poistion_ofspace = i+1
print my_list
Ответ 9
Вы пытались использовать регулярное выражение?
http://docs.python.org/library/re.html#re-syntax
Кстати. Зачем вам нужно "," на втором? Вы узнаете, что после того, как будет записан каждый текст, т.е.
[0]
""
[1]
""
Итак, если вы хотите добавить ",", вы можете просто сделать это после каждой итерации при использовании массива.