1

I am trying to extract sentences from a text, by using Python. Every word in the text are written in a line with additional info related to that word:

Mary Noun Name
loves Verb No-Name
John Noun Name
. Punct No-Name

The sentence boundaries are marked with an empty line. I want to extract the whole sentence that contains words with some particular feature (e.g. sentences with names).

Util now, I have only managed to extract the word of interest, and not the whole sentence. I use .readlines() to read the text line by line. I then loop through the lines and use re and .split('\t') to split the lines, so that every line is represented by a list of 3 elements. I then match the element in the list with the desired value, and can extract the related word, but I can not figure out how I can extract the whole sentence..

Anyone have some advice?

Jon Clements
  • 138,671
  • 33
  • 247
  • 280
Helge
  • 11
  • 2

4 Answers4

1

You could break up by blank lines, split up the types into a set, then use that - an untested example...

text="""Mary Noun Name
loves Verb No-Name
John Noun Name
. Punct No-Name

John Noun Name
loves Verb No-Name
Mary Noun Name
. Punct No-Name"""

from itertools import takewhile

sentences = []
split = iter(text.splitlines())
while True:
    sentence = list(takewhile(bool, split))
    if not sentence:
        break
    types = set(el.split()[1] for el in sentence)
    words = [el.split(' ', 1)[0] for el in sentence]
    sentences.append(
        {
        'sentence': sentence,
        'types': types,
        'words': words
        }
    )


print sum(1 for el in sentences if 'Noun' in el['types']), 'sentences contain Noun'
print sentences[0]['words']
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
  • Haven't mentioned this approach though - if you're dealing with a "standard" file format - then they may well be a corpus reader than NLTK or similar package can already manage for you... (which you may be using anyway when dealing with corpus...) – Jon Clements Oct 15 '12 at 16:50
0

I'd parse the individual rows into dictionaries, which you can group into lists separated by punctuation (or periods).

sentences = []
columns = ('word', 'pos', 'type')

with open('file.txt', 'r') as handle:
    sentence = []

    for row in handle:
        chunks = row.split('\t')
        structure = dict(zip(columns, chunks))

        sentence.append(structure)

        if structure['pos'] == 'Punct':
            sentences.append(sentence)
            sentence = []

Now, sentences contains lists that contains all of the parts of your sentences (if this code works).

I'll leave it to you to figure out how to do the rest. Finding your target sentence should be easy with a couple of for loops.

To print out a sentence given its list, something like this should get you started:

print ' '.join((chunk['word'] for chunk in sentence))
Blender
  • 289,723
  • 53
  • 439
  • 496
0

The existing answers assume the corpus is small enough to read into memory at one go, and build a data structure of sentences which you then filter. If that isn't the case (and even if it is now, it may not be in the future), you'll need to do some sort of generator solution. I'd take a look at the similar question: Python: How to loop through blocks of lines and see if you can make that work for you.

Personally, I think people make more work for themselves by forcing use of a single tool. This particular problem is ready-made for a simple awk filter:

awk -v RS='\n\n' -v FS='\n' -v ORS='\n\n' -v OFS='\n' '/ Name/'

Of course, if you're going to do further processing in python, neither point is valid.

Community
  • 1
  • 1
reedstrm
  • 372
  • 1
  • 9
0

You might want to combine Blender or Jon Clements solution with storing a pickled result of your 'parsed' sentences, so the next time around you can load that information and start searching more quickly.

If your list of sentences does not fit in memory then store the individual sentence information a pickle sequentially in a file if you use the binary pickle, store a length indicator before each pickled sentence.

This extra effort is only worth it if you have to search often and parsing takes substantial time (with huge texts).