【问题标题】:Writing nested dictionary (forest) of a huge depth to a text file将深度巨大的嵌套字典(森林)写入文本文件
【发布时间】:2019-01-01 03:47:03
【问题描述】:

我有一个代表森林(许多非二叉树)的巨大深度字典,我想处理森林并创建一个包含森林所有可能关系的文本文件,例如给定字典:

{'a': {'b': {'c': {}, 'd': {}}, 'g': {}}}

生成的文本文件如下所示:

a b c
a b d
a g

请注意,嵌套字典很大,递归迭代它会导致内存运行时错误。

我尝试做的是将字典递归地转换为列表列表,这会产生运行时错误。代码:

def return_list(forest):
    for ent in forest.keys():
        lst = [new_ent] + grab_children(forest[ent])
        yield lst

def grab_children(father):
    local_list = []
    for key, value in father.items():
        local_list.append(new_key)
        local_list.extend(grab_children(value))
    return local_list

错误:“比较中超出了最大递归深度”RuntimeError

【问题讨论】:

  • 请显示您的递归代码和错误。目前尚不清楚您希望如何从您的示例中排列。
  • DFS,每个终结符写一行。或者,如果可以避免的话,就不要在 python 中进行递归迭代。
  • @Zev 我添加了代码和错误。谢谢
  • 这可能只是为了做sys.setrecursionlimit(1500)

标签: python dictionary tree nested


【解决方案1】:

没有递归,使用生成器和蹦床(写入文件):

data = {'a': {'b': {'c': {}, 'd': {}}, 'g': {}}}


def write_dict(d, s=(), f_out=None):
    if len(d) == 0:
        if f_out:
            f_out.write(' '.join(s) + '\n')
        return

    for k, v in reversed(list(d.items())):
        yield write_dict, v, s + (k, ), f_out


with open('data_out.txt', 'w') as f_out:

    stack = [write_dict(data, f_out=f_out)]

    while stack:
        try:
            v = next(stack[-1])
        except StopIteration:
            del stack[-1]
            continue

        stack.insert(-1, v[0](v[1], v[2], v[3]))

文件包含:

a b c
a b d
a g

【讨论】:

  • 还是递归的,不是吗?
  • @schwobaseggl 不,yield write_dict() 返回新的生成器,它不是递归调用自身。我编辑了我的答案以明确说明 (yield write_dict, v, s)
  • @AndrejKesely 谢谢。如何使用您的代码将打印件写入文件?如果我想要 BFS 而不是 DFS,我该如何修改你的代码?明天我会检查你的答案并接受它。
  • @AndrejKesely 谢谢,如果在应用您的功能时出现“OSError: [Errno 28] No space left on device”错误,您认为我应该怎么做?
  • @Codevan 您的输入文件是否很大?尝试使用较小的部分和/或输出到磁盘上具有足够空间的文件。或者您可以尝试打印到标准输出并将标准输出通过管道传输到 gzip - 这样您将压缩输出。
【解决方案2】:
def l(d):
    return '\n'.join(k + (i and ' ' + i) for k, v in d.items() for i in l(v).split('\n'))
print(l({'a': {'b': {'c': {}, 'd': {}}, 'g': {}}}))

这个输出:

a b c
a b d
a g

【讨论】:

  • 谢谢。如何修改您的代码以打印到文本文件中?
  • 可以使用print函数的file参数,例如with open('filename','w') as file: print(l(your_dict), file=file)
  • 谢谢,但仍然是递归的。
  • 是的,但我认为使用这段代码不会那么容易达到递归限制。
  • 对于我的嵌套字典,确实如此,
【解决方案3】:

非递归方法:

d = {'a': {'b': {'c': {}, 'd': {}}, 'g': {}}}
p = q = []
while True:
    for k, v in d.items():
        if v:
            q.append((v, p + [k]))
        else:
            print(' '.join(p + [k]))
    if not q:
        break
    d, p = q.pop(0)

这个输出:

a g
a b c
a b d

【讨论】:

    猜你喜欢
    • 2019-02-03
    • 2018-05-14
    • 1970-01-01
    • 1970-01-01
    • 2018-06-28
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多