从嵌套字典中的文件中读取最初未知数量的N行,然后在下一次迭代的第N+1行开始

2024-05-08 02:53:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我想处理一个文本文件(逐行)。一个(最初未知)数量的连续行属于同一个实体(即它们与行携带相同的标识符)。例如:

line1: stuff, stuff2, stuff3, ID1, stuff4, stuff5
line2: stuff, stuff2, stuff3, ID1, stuff4, stuff5    
line3: stuff, stuff2, stuff3, ID1, stuff4, stuff5
line4: stuff, stuff2, stuff3, ID2, stuff4, stuff5
line5: stuff, stuff2, stuff3, ID2, stuff4, stuff5
...

在这个虚拟行中,1-3行属于实体ID1,第4-5行属于ID2。我想把每一行都当作字典来读,然后把它们嵌套到一个包含IDX所有字典的字典中(例如,一个ID1字典,分别有3个第1-3行的嵌套字典)。在

更具体地说,我想定义一个函数:

  1. 打开文件
  2. 将实体ID1的所有行(但仅)读入各个字典
  3. 返回包含ID1行嵌套字典的字典

我希望稍后能够再次调用函数,以便在下一个字典中读取以下标识符(ID2)和后面的ID3等的所有行。我遇到的一个问题是,我需要在每一行中测试当前行是否仍带有感兴趣的ID或已经是新的ID。如果它是一个新的,我当然可以停止并返回字典,但是在下一轮(比如,ID2),ID2的第一行已经被读过了,因此我似乎失去了那一行。在

换言之:我希望在遇到一个具有新ID的行时,以某种方式重置函数中的计数器,以便在下一次迭代中使用新ID的第一行不会丢失。在

这似乎是一个很简单的任务,但我想不出一个优雅的方法。目前,我在函数之间传递一些“内存”标志/变量,以便跟踪新ID的第一行是否已经在上一次迭代中被读取。这是相当庞大和容易出错的。在

谢谢你的阅读。。。任何想法/提示都将受到高度赞赏。如果有些地方不清楚,请询问。在

这是我的“解决方案”。从它正确打印字典的意义上来说,它似乎起到了作用(尽管我确信有一种更优雅的方法可以做到这一点)。 我还忘了提到文本文件非常大,因此我想按ID处理它,而不是将整个文件读入内存。在

^{pr2}$

Tags: 文件方法函数实体id字典标识符id2
2条回答

您可以使用字典来跟踪所有IDX列,只需将每行的IDX列添加到字典中相应的列表中,类似于:

from collections import defaultdict
import csv

all_lines_dict = defaultdict(list)

with open('your_file') as f:
  csv_reader = csv.reader(f)            
  for line_list in csv_reader:
    all_lines_dict[line_list[3]].append(line_list)

Csv reader是python标准库的一部分,它使csv文件的读取变得容易。它将把每一行作为列的列表来读取。在

这与您的要求不同,因为每个键不是字典的字典,而是共享IDX键的行的列表。在

如果希望此函数为每个id懒洋洋地返回dict,则应使用yield而不是return使其成为生成器函数。在每个id的末尾,生成该id的dict,然后可以迭代该生成器。在

要处理该文件,请编写一个生成器函数,该函数迭代源代码,除非您向它发送一个值,在这种情况下,它接下来返回该值,然后返回迭代。(例如,这里有一个我自己编写的模块:politer.py。)

然后,如果您不希望,可以通过发送值“back”来轻松解决此问题:

with open(infile, 'r') as f:
    polite_f = politer(f)
    current_id = None
    while True:
        id_dict = {}
        for i, line in enumerate(polite_f):
            id = get_id_from_line(line)
            if id != current_id:
                polite_f.send(line)
                break
            else:
                id_dict[i] = process_line(line)
        if current_id is not None:
            yield id_dict
        current_id = id

请注意,这使状态处理在它所属的生成器中保持抽象。在

相关问题 更多 >