在Python中打印第一个段落

6

我有一本书存在文本文件中,需要打印每个章节的第一段。我认为如果我在\n\n和\n之间找到一个文本,就可以找到答案。这是我的代码,但它没有起作用。你能告诉我错在哪里吗?

lines = [line.rstrip('\n') for line in open('G:\\aa.txt')]

check = -1
first = 0
last = 0

for i in range(len(lines)):
    if lines[i] == "": 
            if lines[i+1]=="":
                check = 1
                first = i +2
    if i+2< len(lines):
        if lines[i+2] == "" and check == 1:
            last = i+2
while (first < last):
    print(lines[first])
    first = first + 1

我在StackOverflow上找到了一段代码,我也尝试了它,但它只打印出一个空数组。
f = open("G:\\aa.txt").readlines()
flag=False
for line in f:
        if line.startswith('\n\n'):
            flag=False
        if flag:
            print(line)
        elif line.strip().endswith('\n'):
            flag=True

我分享了这本书的一个样本章节如下:
I
土地的形势
有一个极具吸引力的人类兴趣领域,就在我们的门外,但迄今为止却很少被探索。它是动物智能领域。
在研究世界野生动物时,所有种类的兴趣中,没有任何一种超越了对它们的思想、道德和作为其心理过程结果而执行的行为的研究。
II
野生动物的脾气和个性
我在这里尝试的是找到大写字母行,并将它们全部放入一个数组中。然后,使用索引方法,通过比较我创建的这个数组的这些元素的索引,找到每个部分的第一段和最后一段。
输出应该像这样:
有一个极具吸引力的人类兴趣领域,就在我们的门外,但迄今为止却很少被探索。它是动物智能领域。
我在这里尝试的是找到大写字母行,并将它们全部放入一个数组中。然后,使用索引方法,通过比较我创建的这个数组的这些元素的索引,找到每个部分的第一段和最后一段。

你能添加实际输入和期望输出吗? - Padraic Cunningham
5个回答

8
如果您想对章节进行分组,可以使用itertools.groupby函数,并将空行作为分隔符:
from itertools import groupby
with open("in.txt") as f:
    for k, sec in groupby(f,key=lambda x: bool(x.strip())):
        if k:
            print(list(sec))

通过一些更多的itertools技巧,我们可以使用大写标题作为分隔符来获取章节:

from itertools import groupby, takewhile

with open("in.txt") as f:
    grps = groupby(f,key=lambda x: x.isupper())
    for k, sec in grps:
        # if we hit a title line
        if k: 
            # pull all paragraphs
            v = next(grps)[1]
            # skip two empty lines after title
            next(v,""), next(v,"")

            # take all lines up to next empty line/second paragraph
            print(list(takewhile(lambda x: bool(x.strip()), v)))

这将为您提供:

['There is a vast field of fascinating human interest, lying only just outside our doors, which as yet has been but little explored. It is the Field of Animal Intelligence.\n']
['What I am trying to do here is, find the uppercase lines, and put them all in an array. Then, using the index method, I will find the first and last paragraphs of each section by comparing the indexes of these elements of this array I created.']

每个部分的开头都有一个全大写的标题,因此一旦我们看到它,就知道有两个空行,然后是第一个段落,这个模式会重复出现。
使用循环来分解它:
from itertools import groupby  
from itertools import groupby
def parse_sec(bk):
    with open(bk) as f:
        grps = groupby(f, key=lambda x: bool(x.isupper()))
        for k, sec in grps:
            if k:
                print("First paragraph from section titled :{}".format(next(sec).rstrip()))
                v = next(grps)[1]
                next(v, ""),next(v,"")
                for line in v:
                    if not line.strip():
                        break
                    print(line)

针对您的文本:

In [11]: cat -E in.txt

THE LAY OF THE LAND$
$
$
There is a vast field of fascinating human interest, lying only just outside our doors, which as yet has been but little explored. It is the Field of Animal Intelligence.$
$
Of all the kinds of interest attaching to the study of the world's wild animals, there are none that surpass the study of their minds, their morals, and the acts that they perform as the results of their mental processes.$
$
$
WILD ANIMAL TEMPERAMENT & INDIVIDUALITY$
$
$
What I am trying to do here is, find the uppercase lines, and put them all in an array. Then, using the index method, I will find the first and last paragraphs of each section by comparing the indexes of these elements of this array I created.

美元符号代表换行符,输出结果为:
In [12]: parse_sec("in.txt")
First paragraph from section titled :THE LAY OF THE LAND
There is a vast field of fascinating human interest, lying only just outside our doors, which as yet has been but little explored. It is the Field of Animal Intelligence.

First paragraph from section titled :WILD ANIMAL TEMPERAMENT & INDIVIDUALITY
What I am trying to do here is, find the uppercase lines, and put them all in an array. Then, using the index method, I will find the first and last paragraphs of each section by comparing the indexes of these elements of this array I created.

很酷,我可以使用这段代码看到每个部分..但我只想看到它们的第一段..我该如何提取? - Tuğcan Demir
@TuğcanDemir,您在问题中想要从输入中提取什么? - Padraic Cunningham
非常感谢!但是还存在一些问题,因为当我使用这段代码时,我会再次看到每个部分的所有段落。标题和第一个段落之间应该有两个空行,但我无法控制它。我不能在我的问题上添加两个空行,网站不允许:/ - Tuğcan Demir
@TuğcanDemir,你只需要再次调用next(v)来跳过第二个空行。 - Padraic Cunningham
@TuğcanDemir,编辑应该注意额外的空行,现在格式应该与您的匹配。 - Padraic Cunningham
显示剩余2条评论

1

总是有正则表达式……

import re
with open("in.txt", "r") as fi:
    data = fi.read()
paras = re.findall(r"""
                   [IVXLCDM]+\n\n   # Line of Roman numeral characters
                   [^a-z]+\n\n      # Line without lower case characters
                   (.*?)\n          # First paragraph line
                   """, data, re.VERBOSE)
print "\n\n".join(paras)

这个有点长毛了:“有些人在面对问题时,会想‘我知道了,我来用正则表达式解决。’现在他们有两个问题了。” [IV]+ 哦? - msw
如何打印第一个段落而不是第一行? - Tuğcan Demir
所以,我也用了你的代码找到了我的方法...非常感谢 :) - Tuğcan Demir

0

TXR解决方案

$ txr firstpar.txr data
有一个广阔的、迷人的人类兴趣领域,就在我们的门外,但迄今为止还很少被探索。这就是动物智能领域。
我在这里尝试的是,找到大写字母行,并将它们全部放入一个数组中。然后,使用索引方法,通过比较我创建的这个数组的元素的索引,找到每个部分的第一和最后一段。

firstpar.txr中的代码:

@(repeat)
@num
@title @firstpar @ (require (and (< (length num) 5) [some title chr-isupper] (not [some title chr-islower]))) @ (do (put-line firstpar)) @(end)

基本上,我们正在搜索输入以匹配三元素多行模式,该模式绑定numtitlefirstpar变量。现在,这种模式可能会在错误的位置匹配,因此使用require断言添加一些约束启发式算法。要求节号为短行,并且标题行必须包含一些大写字母,而没有小写字母。此表达式是用TXR Lisp编写的。

如果我们符合此约束条件,则输出捕获在firstpar变量中的字符串。


0

逐行查看你找到的代码。

f = open("G:\\aa.txt").readlines()
flag=False
for line in f:
        if line.startswith('\n\n'):
            flag=True
        if flag:
            print(line)
        elif line.strip().endswith('\n'):
            flag=True

看起来它从未将标记变量设置为true。

如果您可以分享一些来自您的书中的示例,对每个人都更有帮助。


我分享了你分享的相同代码,只需在第一个if块中将标志设置为true。 - st.
当我将第一个标志设置为true时,它会在每行上添加2个空行。 - Tuğcan Demir

0

只要没有全大写的段落,这个应该可以工作:

    f = open('file.txt')

    for line in f:
    line = line.strip()
    if line:  
        for c in line:
            if c < 'A' or c > 'Z': # check for non-uppercase chars
                break
        else:        # means the line is made of all caps i.e. I, II, etc, meaning new section
            f.readline()  # discard chapter headers and empty lines
            f.readline()
            f.readline()
            print(f.readline().rstrip()) # print first paragraph

    f.close()

如果您想获取最后一段,可以跟踪包含小写字符的最后一行,并且一旦找到全大写行(I、II等),表示新部分,则打印最近的行,因为那将是上一节中的最后一段。

@TuğcanDemir 我进行了一些微小的更改,删除了空行并使代码更易读。这段代码(以及之前的版本)与您提供的示例一起运行良好。您能否提供导致您获得这些结果的示例部分? - SoreDakeNoKoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接