Python 从文本文件中随机选择句子,找到相应的ID号

Python 从文本文件中随机选择句子,找到相应的ID号,python,regex,random,linguistics,Python,Regex,Random,Linguistics,我正在帮助我的一位教授进行一项研究项目,该项目涉及从一组20个文本文件中随机抽取1000个句子。这些都是来自当代美国英语语料库的数据,如果有人熟悉的话。在这些文本文件中,数据的排列方式如下: 我必须这样说:为了准备这次讲座,我读了或在某些情况下重读了西德尼·胡克的一些著作。我读它们仅仅是为了给我一个正确的起点,为纪念西德尼·胡克的演讲做准备。但相反,我发现自己被灌输了一套与不同环境、不同场合相关的想法 4000349我想我最为人所知的是我的智慧和学识,但事实上,我之所以如此出名,是因为我是一位著

我正在帮助我的一位教授进行一项研究项目,该项目涉及从一组20个文本文件中随机抽取1000个句子。这些都是来自当代美国英语语料库的数据,如果有人熟悉的话。在这些文本文件中,数据的排列方式如下:

我必须这样说:为了准备这次讲座,我读了或在某些情况下重读了西德尼·胡克的一些著作。我读它们仅仅是为了给我一个正确的起点,为纪念西德尼·胡克的演讲做准备。但相反,我发现自己被灌输了一套与不同环境、不同场合相关的想法 4000349我想我最为人所知的是我的智慧和学识,但事实上,我之所以如此出名,是因为我是一位著名的保守主义者,也是耶鲁学院院长。这就是我被任命的消息出现在《华尔街日报》和《全国评论》上的原因。耶鲁大学的院长们通常不会看到这一消息,而且这对他们也没有多大帮助 区块报价>

因此,有数百段,每段开头都有一个六位数,前面有一个。这个数字对应于句子的来源。我需要从这些文件中随机抽取一些句子,并获得六位数的数字来识别它们的来源。因此,理想情况下,我会得到如下结果:

我阅读它们仅仅是为了给我一个正确的起点,为纪念西德尼·胡克的演讲做准备 4000349我想我最为人所知的是我的智慧和学识,但事实上,我之所以如此出名,是因为我是一位著名的保守主义者,也是耶鲁学院院长

在stackoverflow的善良灵魂的帮助下,我成功地从文件中随机获得了一些句子,但我不知道如何获得附加到它们的数字。例如,如果我从段落中间提取一个句子,我如何能够从段落开头获得数字。有谁能帮我想个办法吗?这是我到目前为止的代码,它成功地提取了句子

# -*- coding: utf-8 -*-

import re
from random import sample

sentences = []
for i in range(1990,2013):
    with open('w_acad_{}.txt'.format(i)) as f:
        sentences += re.findall(r".*?[\.\!\?]+", f.read())

selected = sample(sentences, 2000)
with open('out.txt', 'w') as f:
    f.write('\n'.join(selected))

也许您可以使用正则表达式提取每个段落及其源id,然后从段落中提取句子,类似于您目前的做法。这将有助于您理解以下段落:

# with open... etc.
for source_id, paragraph in re.findall(r"(##\d+)([^#]+)", f.read()):
    sentences += [(source_id, sentence) for sentence in re.findall(r".*?[\.\!\?]+", paragraph)]

现在,句子应该是一个元组列表,如“123”,“一个句子”,您可以从中进行与以前相同的采样。

一般来说,为了避免一次将潜在的大文件加载到内存中,您可以使用-只需传递一个迭代器,该迭代器将生成标记为-数字的句子:

#!/usr/bin/env python
import re
import nltk  # $ pip install nltk

def paragraphs(file):
    """Yield blank-line separated paragraphs labeled with ##-numbers."""
    lines = []
    for line in file:
        if line.strip():
            lines.append(line)
        elif lines:  # blank line, the end of a non-empty paragraph
            paragraph = ''.join(lines)
            numbers = re.findall(r'##([0-9]+)', paragraph)  # only ASCII-digits
            assert len(numbers) == 1  # only one ##-number per paragraph
            yield int(numbers[0]), paragraph
            del lines[:]

def sentences(filenames):
    for filename in filenames:
        with open(filename) as file:
            for number, paragraph in paragraphs(file):
                for sentence in nltk.sent_tokenize(paragraph):
                    yield number, sentence

filenames = ('w_acad_%d.txt' % n for n in range(1990, 2013))
print(reservoir_sample(sentences(filenames), 2000))
在哪里


可能是比r.*?[\.\!\?]+正则表达式更健壮的解决方案。

嘿,这个答案太棒了!我很抱歉,我花了这么长时间来回复,我一直有点忙,没有在这个项目上的工作。我使用了您的代码,包括您给我的示例定义,代码可以编译,但它打印的全部内容是:“[]”您知道这是为什么吗?@K.Swan代码期望的输入格式可能与实际格式不同。您应该修改段落函数以匹配文件的实际格式。如果你不能;创建一个最小的示例输入,描述假设,例如,段落之间有空行是否正确?如果你对实践感兴趣,一个简单的基于正则表达式的解决方案,比如@pzelasko-answer,应该足够了。