воссоздать многоканальные строки из токенов с указанными индексами и источником текста - PullRequest
0 голосов
/ 06 апреля 2020

Я готовлю сценарий, который воссоздает строки из нескольких токенов из текста токена для токенов, которые имеют определенные c метки. Мои токены связаны с их начальными и конечными индексами в исходном тексте.

Это пример фрагмента текста:

t = "Breakfast at Tiffany's is a novella by Truman Capote."

Структура данных токенов, содержащая исходные текстовые индексы и метки:

[(['Breakfast', 0, 9], 'BOOK'),
 (['at', 10, 12], 'BOOK'),
 (['Tiffany', 13, 20], 'BOOK'),
 (["'", 20, 21], 'BOOK'),
 (['s', 21, 22], 'BOOK'),
 (['is', 23, 25], 'O'),
 (['a', 26, 27], 'O'),
 (['novella', 28, 35], 'O'),
 (['by', 36, 38], 'O'),
 (['Truman', 39, 45], 'PER'),
 (['Capote', 46, 52], 'PER'),
 (['.', 52, 53], 'O')]

Эта структура данных была сгенерирована из t следующим образом

import re

tokens = [[m.group(0), m.start(), m.end()] for m in re.finditer(r"\w+|[^\w\s]", t, re.UNICODE)]
tags = ['BOOK', 'BOOK', 'BOOK', 'BOOK', 'BOOK', 'O', 'O', 'O', 'O', 'PER', 'PER', 'O']
token_tuples = list(zip(tokens, tags))

Что бы я хотел, чтобы мой скрипт выполнял итерацию по token_tuples, и если он встречает не - O токен, он отрывается от основной итерации и восстанавливает помеченный диапазон нескольких токенов, пока не достигнет ближайшего токена с O.

Это текущий скрипт:

for i in range(len(token_tuples)):

    if token_tuples[i][1] != 'O':

        tag = token_tuples[i][1]
        start_ix = token_tuples[i][0][1]

        slider = i+1

        while slider < len(token_tuples):

            if tag != token_tuples[slider][1]:

                end_ix = token_tuples[slider][0][2]

                print((t[start_ix:end_ix], tag))
                break

            else:
                slider+=1

Это печатает:

("Breakfast at Tiffany's is", 'BOOK')
("at Tiffany's is", 'BOOK')
("Tiffany's is", 'BOOK')
("'s is", 'BOOK')
('s is', 'BOOK')
('Truman Capote.', 'PER')
('Capote.', 'PER')

Что нужно изменить, чтобы вывод для этого примера был:

> ("Breakfast at Tiffany's", "BOOK")
> ("Truman Capote", "PER")

1 Ответ

0 голосов
/ 06 апреля 2020

Вот одно из решений. Если вы можете придумать что-то менее затянутое, я с удовольствием выберу ваш ответ вместо этого!

def extract_entities(t, token_tuples):

    entities = []
    tag = ''

    for i in range(len(token_tuples)):

        if token_tuples[i][1] != 'O':

            if token_tuples[i][1] != tag:
                tag = token_tuples[i][1]
                start_ix = token_tuples[i][0][1]

            if i+1 < len(token_tuples):

                if tag != token_tuples[i+1][1]:
                    end_ix = token_tuples[i][0][2]
                    entities.append((t[start_ix:end_ix], tag))
                    tag = ''

    return(entities)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...