簡體   English   中英

從此Python生成器中刪除遞歸

[英]Remove recursion from this Python generator

我有一個生成器,可以對嵌套字典中特定深度的所有鍵組合進行迭代:

def iter_dict(levels, input_dict, items=[], sort=False, **sort_args):
    for dict_key, val in (sorted(input_dict.items(), **sort_args) if
                          sort else input_dict.items()):
        if levels == 1:
            yield items + [(dict_key, val)]
        else:
            yield from iter_dict(levels - 1, val, items + [(dict_key, val)])

因此它的行為如下:

>>> d = {'a': 1, 'b': 2}
>>> list(iter_dict(1, d))
[[('a', 1)], [('b', 2)]]

>>> d = {'a': {'c': 1}, 'b': {'d' : 2}}
>>> list(iter_dict(1, d))
[[('a', {'c': 1})], [('b', {'d': 2})]]
>>> list(iter_dict(2, d))
[[('a', {'c': 1}), ('c', 1)], [('b', {'d': 2}), ('d', 2)]]

生成器上的每次迭代都會返回一個元組列表,第n個元組是嵌套字典中深度為n的(key, value)

但是我正在龐大的詞典上實現此功能,並且擔心達到最大遞歸深度級別。

如何重寫生成器以刪除遞歸?

但是我正在龐大的詞典上實現此功能,並且擔心達到最大遞歸深度級別

除非您的詞典實際具有1000多個級別的嵌套,否則這不是問題。 最大遞歸深度實際上只是深度 ; 分支因素不是問題。 也就是說,這對於運行時間可能是一個很大的問題,但是您不會從中得到最大的遞歸深度錯誤(如果沒有遞歸,運行時間將是相同的)。

如何重寫生成器以刪除遞歸?

我猜這可以通過使用堆棧並在堆棧上存儲鍵序列(當前子字典的所有鍵)來完成。 這樣的解決方案可能會涉及更多點,並且不如遞歸算法那么優雅,因此鑒於上述情況,我認為不值得為此付出努力。

但是,無論如何,您可以進行以下操作(略有簡化,無需排序):

from functools import reduce
def iter_dict(levels, input_dict):
    def get_nested(keys):
        return reduce(lambda d, k: d[k], keys, input_dict)
    stack = [[k] for k in input_dict]
    while stack:
        keys = stack.pop()
        if len(keys) == levels:
            yield [(k, get_nested(keys[:i])) for i, k in enumerate(keys, 1)]
        else:
            stack.extend(keys + [k] for k in get_nested(keys))

例:

>>> d = {'a': {'c': 1, "e": 2}, 'b': {'d' : 3, "f": 4}}
>>> list(iter_dict(2, d))
[[('a', {'c': 1, 'e': 2}), ('e', 2)],
 [('a', {'c': 1, 'e': 2}), ('c', 1)],
 [('b', {'d': 3, 'f': 4}), ('f', 4)],
 [('b', {'d': 3, 'f': 4}), ('d', 3)]]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM