将文件按段落分隔读入Python数组

9

我有一个文本文件,想要将它读入三个不同的数组中:array1、array2和array3。第一段放在array1中,第二段放在array2中,以此类推。第四段将被放置在array1的第二个元素中,依此类推。段落之间由一个空行分隔。你有什么想法吗?

7个回答

12

这是我会尝试的基本代码:

f = open('data.txt', 'r')

data = f.read()
array1 = []
array2 = []
array3 = []
splat = data.split("\n\n")
for number, paragraph in enumerate(splat, 1):
    if number % 3 == 1:
        array1 += [paragraph]
    elif number % 3 == 2:
        array2 += [paragraph]
    elif number % 3 == 0:
        array3 += [paragraph]

这应该足以让您入门。如果文件中的段落由两个换行符分隔,则“\n\n”应该可以用于将它们拆分。


2
最好使用with open('data.txt', 'r') as f: - MERose

4
import itertools as it


def paragraphs(fileobj, separator='\n'):
    """Iterate a fileobject by paragraph"""
    ## Makes no assumptions about the encoding used in the file
    lines = []
    for line in fileobj:
        if line == separator and lines:
            yield ''.join(lines)
            lines = []
        else:
            lines.append(line)
    yield ''.join(lines)

paragraph_lists = [[], [], []]
with open('/Users/robdev/Desktop/test.txt') as f:
    paras = paragraphs(f)
    for para, group in it.izip(paras, it.cycle(paragraph_lists)):
        group.append(para)

print paragraph_lists

使用流式状态机方法来按段拆分文本是一个巨大的优势!这应该是首选解决方案,而不是简单地使用split("\n\n"),因为它有许多次优边缘情况。 - traal

2

我知道这个问题很久以前就被问过了,但是我想提供一些意见,以便在某个时候对其他人有用。我找到了一种更简单的方法,可以根据段落分隔符(可以是 \n 或空格或其他任何字符)将输入文件拆分成段落,并且下面是您所提出问题的代码片段:

with open("input.txt", "r") as input:
    input_ = input.read().split("\n\n")   #\n\n denotes there is a blank line in between paragraphs.

执行此命令后,如果尝试打印 input_[0],将显示第一段落;input_[1] 将显示第二段落,以此类推。因此,它将输入文件中的所有段落放入列表中,每个列表元素包含输入文件中的一个段落。


1

这段代码将搜索两个点之间的行:

rr = [] #Array for saving lines    
for f in file_list:
    with open(f, 'rt') as fl:
        lines = fl.read()
        lines = lines[lines.find('String1'):lines.find('String2')] 
        rr.append(lines)

1

因为我觉得炫耀一下:

with open('data.txt') as f:
    f = list(f)
    a, b, c = (list(__import__('itertools').islice(f, i, None, 3)) for i in range(3))

那不会分割文件的内容;islice对象将迭代文件中的行。 - Rob Cowie
每个迭代器都是文件中一部分行的迭代器,然后明确地转换为一个“列表”。问题在哪里?编辑:经过测试发现,由于我不理解的原因,所有内容最终都会出现在第一个迭代器中。这可以通过从列表而不是流中读取来解决(这是我最初测试的内容);相应地进行了编辑。 - Karl Knechtel
是的,OP希望迭代段落而不是行。 - Rob Cowie
跟进:问题出现是因为每个islice在下一个操作之前尝试完全读取流。很烦人;应该有一种更优雅的方法来多路复用流。@Rob,“段落”通常由文本文件中的换行符定义;如果文本行被明确包装,则OP需要说明,并确定分隔段落的确切内容。 - Karl Knechtel
我认为段落通常由一个空行分隔,因此是两个换行符'\n\n'。一个段落中可能有(并且很可能有)多行文本(因此有多个换行符)。因此,简单的基于行的迭代是不够的。无论如何,“islice”问题都是一个有趣的问题。 - Rob Cowie
如果我们将\n\n作为分隔符,那么将文件读入段落列表非常简单,只需使用f.read().split('\n\n')即可。尽管由于流处理无法正常工作,所以现在已经没有意义了;最好使用列表切片。 - Karl Knechtel

0

使用切片也可以。

par_separator = "\n\n"
paragraphs = "1\n\n2\n\n3\n\n4\n\n5\n\n6".split(par_separator)
a,b,c = paragraphs[0:len(paragraphs):3], paragraphs[1:len(paragraphs):3],\
        paragraphs[2:len(paragraphs):3] 

切片语法:[起始索引,终止索引,步长]


0
更优雅的绕过切片的方法:
def grouper(n, iterable, fillvalue=None):
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)

for p in grouper(5,[sent.strip() for sent in text.split('\n') if sent !='']):
    print p

请确保在最终文本中处理None


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