Разбейте предложение на его токены как символьную аннотацию Python - PullRequest
3 голосов
/ 09 апреля 2020

После долгих поисков я не нашел ответа на свой вопрос, поэтому решил поставить свой вопрос здесь. Я пытаюсь добиться какого-то определенного c результата с RE и NLTK. Учитывая предложение, для каждого символа я должен использовать формат BIS, то есть помечать каждый символ как B (beginning of the token), I (intermediate or end position of the token), S for space. Например, с учетом предложения:

Ручка находится на столе.

Система должна будет предоставить следующий вывод:

BIISBIISBISBISBIISBIIIIB

который можно прочитать как:

<3-char token> <space> <3-char token> <space> <2-char token> <space> <2-char token> <space> <3-char token> <space> <5-char token> <1-char token>)

Мой результат довольно близок, но вместо:

BIISBIISBISBISBIISBIIIIB 

Я получаю:

BIISBIISBISBISBIISBIIIISB

Значение Я получаю пробел между table и точкой . Выходные данные должны быть:

<3-char token> <space> <3-char token> <space> <2-char token> <space> <2-char token> <space> <3-char token> <space> <5-char token> <1-char token>

Мое:

<3-char token> <space> <3-char token> <space> <2-char token> <space> <2-char token> <space> <3-char token> <space> <5-char token> <space> <1-char token>

Мой код пока:

from nltk.tokenize import word_tokenize
import re
p = "The pen is on the table."
# Split text into words using NLTK
text = word_tokenize(p)
print(text)
initial_char = [x.replace(x[0],'B') for x in text]
print(initial_char)
def listToString(s):  
    # initialize an empty string 
    str1 = " " 
    # return string   
    return (str1.join(s)) 
new = listToString(initial_char)
print(new)
def start_from_sec(my_text):
    return ' '.join([f'{word[0]}{(len(word) - 1) * "I"}' for word in my_text.split()])
res = start_from_sec(new)
p = re.sub(' ', 'S', res)
print(p)

1 Ответ

2 голосов
/ 09 апреля 2020

Вы можете использовать одно регулярное выражение для токенизации строки:

(\w)(\w*)|([^\w\s])|\s

См. Демо регулярное выражение

Детали шаблона

  • (\w)(\w*) - группа 1: любое слово char (буква, ди git или _), а затем группа 2: любое 0 или более слов символа
  • | - или
  • ([^\w\s]) - Группа 3: любой символ, кроме слова и символа пробела
  • | - или
  • \s - символа пробела

Если группа 1 совпадает, возвращаемое значение равно B + то же число I с, что и число символов в группе 2. Если группа 3 совпадает, замените на B. В противном случае, пробел сопоставляется, замените на S.

. Это можно настроить дополнительно, например,

  • . Обрабатывать _ только как знаки пунктуации: r'([^\W_])([^\W_]*)|([^\w\s]|_)|\s'
  • Замените один или несколько пробелов одним S: r'([^\W_])([^\W_]*)|([^\w\s]|_)|\s+'

См. Python демонстрацию онлайн :

import re
p = "The pen is on the table."
def repl(x):
    if x.group(1):
        return "B{}".format("I"*len(x.group(2)))
    elif x.group(3):
        return "B"
    else:
        return "S"

print( re.sub(r'(\w)(\w*)|([^\w\s])|\s', repl, p) )
# => BIISBIISBISBISBIISBIIIIB
...