到目前为止,最简单的新手解决方案可能是史蒂夫建议的方式:只需迭代行,并使用标志来跟踪最后一行是否为空行。
但是如果你想要一个更高层次的解决方案,你需要在更高层次上重新思考这个问题。您实际上要指定的是每个段落的第一行,但第一行,其中“段落”是由空行分隔的内容。正确的?
那么,你怎么能这样做呢?好吧,您可以'\n\n'
像 on 一样轻松拆分 on \n
。所以:
paragraphs = document.split('\n\n')
first_lines = [paragraph.partition('\n')[0] for paragraph in paragraphs]
popped_lines = first_lines[1:]
(我在这里使用partition
而不是,split
因为它只在第一个拆分'\n'
,其余部分不理会,并且因为它可以正确处理单行段落 - 这paragraph.split('\n', 1)
不会。)
但是您不想要弹出行的列表,您想要除弹出行之外的所有内容的列表,对吗?
paragraphs = document.split('\n\n')
first, rest = paragraphs[0], paragraphs[1:]
rest_edited = [paragraph.partition('\n')[1] for paragraph in rest]
如果你想把它变成一个文档:
all_edited = [first] + rest_edited
document_edited = '\n\n'.join(all_edited)
您可以通过使用切片分配来缩短它,尽管我不确定它是否具有可读性:
paragraphs = document.split('\n\n')
paragraphs[1:] = [paragraph.partition('\n')[1] for paragraph in paragraphs[1:]]
document_edited = '\n\n'.join(paragraphs)
正如 JF Sebastian 指出的那样,这个问题有点模棱两可。“空白行”是指“空行”还是“只有空格的行”?如果是后者,事情就有点复杂了,最简单的解决方案可能是一个简单的正则表达式 ( r'\n\s*\n'
) 来分割成段落。
同时,如果您拥有的是一系列行(请注意,文件是一系列行!)而不是一个大字符串,您可以通过几种不同的方式完全不拆分。
例如,段落是一组非空行,对吧?因此,您可以使用该groupby
函数来获取它们:
groups = itertools.groupby(lines, bool)
或者,如果“空白”并不意味着“空”:
groups = itertools.groupby(lines, lambda line: not line.strip())
请注意,这将为您(False, <sequence of lines>)
提供每个段落和(True, <sequence of blank lines>)
每个空白行。如果你想按原样保留空行,你可以——但如果你很高兴只用一个空行替换每一行空行(如果“空白”确实意味着“空”,那么你显然是这样),它可能是更容易丢弃空白段落:
paragraphs = (group for (key, group) in paragraphs if not key)
然后,您可以从除第一个组之外的所有元素中删除第一个元素,最后将这些组链接在一起形成一个大序列:
first = next(paragraphs)
edited_paragraphs = (itertools.islice(paragraph, 1) for paragraph in paragraphs)
edited_document = itertools.chain(first, *edited_paragraphs)
最后,如果您连续运行多个空行怎么办?好吧,首先你必须决定如何处理它们。如果你有两个空行,你会删除第二个吗?如果是这样,你是删除下一段的第一行(因为它最初是在一个空行之后),还是不删除(因为它之后的空行已经被删除了)?如果你连续三个呢?分裂'\n\n'
会做一件事,分裂会做另一件事,还有另一'\n\s*\n'
件事groupby
……但在你知道你想要什么之前,当然不可能说哪个是“正确的”或如何“修复”其他的。