2013-03-20 9 views
7

Sto cercando di ottenere le frasi da una stringa che contiene una sottostringa data usando python.Trovare la frase circostante di un carattere/parola in una stringa

Ho accesso alla stringa (un abstract accademico) e un elenco di punti salienti con indici di inizio e fine. Per esempio:

{ 
    abstract: "...long abstract here..." 
    highlights: [ 
    { 
     concept: 'a word', 
     start: 1, 
     end: 10 
    } 
    { 
     concept: 'cancer', 
     start: 123, 
     end: 135 
    } 
    ] 
} 

sto loop su ogni pezzo forte, la localizzazione è iniziare indice in astratto (alla fine non importa come ho solo bisogno di ottenere una posizione all'interno di una frase), e poi in qualche modo bisogno di Identificare la frase in cui si verifica l'indice.

Sono in grado di convertire l'abstract in frasi usando nltk.tonenize.sent_tokenize, ma facendo ciò renderò la posizione dell'indice inutile.

Come devo risolvere questo problema? Suppongo che le regex siano un'opzione ma il tokenizer nltk sembra un modo così bello di farlo che sarebbe un peccato non usarlo .. O in qualche modo resettare l'indice di avvio trovando il numero di caratteri dal precedente punto/punto esclamativo/punto interrogativo?

+0

Questo appare come JSON. – squiguy

+0

Sì, sto manipolando i dati da un endpoint API. – Elise

+0

Potrebbe essere costoso ma potresti passare attraverso le frasi e ricalcolare gli indici delle frasi dalla lunghezza, quindi cercare quell'indice – user1937198

risposta

6

Hai ragione, il tokenizzatore NLTK è davvero quello che dovresti usare in questa situazione poiché è abbastanza robusto da gestire la delimitazione di tutte le frasi, compresa la conclusione di una frase con una "citazione". Si può fare qualcosa di simile (paragraph da un generatore casuale):

Inizia con,

from nltk.tokenize import sent_tokenize 

paragraph = "How does chickens harden over the acceptance? Chickens comprises coffee. Chickens crushes a popular vet next to the eater. Will chickens sweep beneath a project? Coffee funds chickens. Chickens abides against an ineffective drill." 
highlights = ["vet","funds"] 
sentencesWithHighlights = [] 

modo più intuitivo:

for sentence in sent_tokenize(paragraph): 
    for highlight in highlights: 
     if highlight in sentence: 
      sentencesWithHighlights.append(sentence) 
      break 

Ma con questo metodo in realtà abbiamo ciò che è effettivamente un ciclo for nidificato a 3x. Questo perché prima controlliamo ogni sentence, quindi ogni highlight, quindi ogni sottosequenza nello sentence per il highlight.

Siamo in grado di ottenere prestazioni migliori dal momento che sappiamo l'indice di partenza per ogni pezzo forte:

highlightIndices = [100,169] 
subtractFromIndex = 0 
for sentence in sent_tokenize(paragraph): 
    for index in highlightIndices: 
     if 0 < index - subtractFromIndex < len(sentence): 
      sentencesWithHighlights.append(sentence) 
      break 
    subtractFromIndex += len(sentence) 

In entrambi i casi si ottiene:

sentencesWithHighlights = ['Chickens crushes a popular vet next to the eater.', 'Coffee funds chickens.'] 
+1

Questo è esattamente quello che stavo cercando, semplice e facile da capire, grazie! – Elise

1

Suppongo che tutte le frasi terminano con uno di questi tre personaggi: !?.

Che dire loop sopra l'elenco dei punti salienti, la creazione di un gruppo regexp:

(?:list|of|your highlights) 

Poi corrispondenza tutto il tuo astratto contro questo regexp:

/(?:[\.!\?]|^)\s*([^\.!\?]*(?:list|of|your highlights)[^\.!\?]*?)(?=\s*[\.!\?])/ig 

in questo modo si otterrebbe la frase contenente almeno uno dei tuoi punti salienti nel primo subgrou p di ogni partita (RegExr).

0

Un'altra opzione (anche se è difficile dire quanto è affidabile sarebbe con testo variabile definita), sarebbe quello di dividere il testo in un elenco di frasi e di prova contro di loro:

re.split('(?<=\?|!|\.)\s{0,2}(?=[A-Z]|$)', text) 
Problemi correlati