2013-03-20 10 views
7

pythonを使って指定された部分文字列を含む文字列から文を取得しようとしています。文字列内の文字/単語の周囲文を見つける

私は文字列(学術の要約)と、開始および終了インデックスを含むハイライトのリストにアクセスできます。たとえば:

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

私は、それぞれのハイライトをループしています(私はちょうどセンテンス内の位置を取得する必要があるとして、最後は本当に重要ではありません)、それは抽象的で、インデックスを開始だ位置し、その後何とかする必要がインデックスが存在する文を特定します。

nltk.tonenize.sent_tokenizeを使用して要約をトークン化することができますが、これを行うことでインデックスの位置が無駄になります。

この問題を解決するにはどうすればよいですか?私はregexesはオプションだと思うが、nltkトークナイザは、それを使用することが恥ずましいだろうそれをやってのような良い方法と思われる..または何とか前の完全な停止以来の文字の数を見つけることによって開始インデックスをリセット/感嘆符/疑問符?

+0

これは、JSONのように見えます。 – squiguy

+0

はい、APIエンドポイントからデータを操作しています。 – Elise

+0

高価かもしれませんが、文章を見て長さから文章のインデックスを再計算してから、その索引を検索してください – user1937198

答えて

6

あなたは正しいです、 NLTKトークナイザは、実際には、文章を「引用」で終わらせることを含むすべての文の区切りを処理するのに十分な堅牢性を備えているため、この状況で使用する必要があります。

スタート、

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 = [] 

ほとんど直感的な方法:

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

しかし、我々は実際に持っているこの方法を使用しますが、この(ランダム発生器からparagraph)のような何かを行うことができます効果的に3xネストされたループforループです。これは、最初にそれぞれsentenceを確認してから、それぞれhighlightを確認してから、highlightsentenceに各サブシーケンスをチェックするためです。私たちはそれぞれのハイライトの開始インデックスを知っているので、

私たちはより良いパフォーマンスを得ることができます:我々が得るいずれの場合も

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) 

を:

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

これは私が探していたものです。 – Elise

1

私はすべてのあなたの文章はこれら三つの文字のいずれかで終了することを前提としています!?.

どの正規表現のグループを作成し、ハイライトのリストをループについて:

(?:list|of|your highlights) 

が続いに対するあなたの全体の抽象マッチングこの正規表現:

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

この方法では、まずsubgrouであなたのハイライトの少なくとも一つを含む文になるだろう各試合のp(RegExr)。

0

別のオプション(それは可変的定義のテキストとなりますどの程度信頼できると言うことは難しいが)、それらに対する文章やテストのリストにテキストを分割するようになります:

re.split('(?<=\?|!|\.)\s{0,2}(?=[A-Z]|$)', text) 
関連する問題