我碰到了可以使字典扁平化的功能:
def flatten(dictionnary, container=None):
if container is None:
container = []
for k, v in dictionnary.items():
container.append(k)
if v:
flatten(v, container)
return container
为了测试它,我创建了一个嵌套n
的字典,如下所示:
nesteddict = {}
for i in range(n, 0, -1):
emptydict = {}
emptydict[i] = nesteddict
nesteddict = emptydict
该功能在n
小于999时起作用,否则它将达到递归限制:
RecursionError: maximum recursion depth exceeded while calling a Python object
因此,经过一点搜索之后,似乎any recursive function can rewritten to iteration了,但是我看不到对于必须产生相同结果的函数该怎么做。
在玩此游戏时遇到的另一个怪异问题是,如果我尝试下面的n >= 998
代码:
nesteddict = {}
for i in range(n, 0, -1):
emptydict = {}
emptydict[i] = nesteddict
nesteddict = emptydict
print(nesteddict)
我遇到递归错误:
RecursionError: maximum recursion depth exceeded while getting the repr of an object
这很奇怪,因为我在这里看不到任何递归。
答案 0 :(得分:6)
您应该将字典的迭代器保存在堆栈中,而不是将字典保存在堆栈中。
这样,您可以在命令中恢复迭代器。
此外,因为您是按顺序暂停和恢复迭代器的执行,所以结果始终将根据字典的顺序。
顺便说一句,@ iBug,字典按照3.7的Python规范进行排序
def flatten(dictionary, container=None):
if container is None:
container = []
iterators = []
iterator = iter(dictionary.items())
while True:
for k, v in iterator:
container.append(k)
if v:
# Save the current iterator for later
iterators.append(iterator)
# Run on the new dict
iterator = iter(v.items())
break
# Current iterator is done, fetch the next one
else:
try:
iterator = iterators.pop()
except IndexError:
return container
print(flatten({1: None, 2: {3: None, 4: None}, 5: None}))
[1, 2, 3, 4, 5]
答案 1 :(得分:3)
从逻辑上讲,嵌套字典(和列表)是一种递归,因此,如果要避免逻辑递归,那是不可能的。
但是,由于递归只是递归,因此您可以保留自己的堆栈并在循环中进行模拟:
def flatten(dct, c=None):
if c is None:
c = []
stack = [dct]
while stack: # non-empty
d = stack.pop()
for k, v in d.items():
c.append(k)
if v:
stack.append(v)
return c
此函数使用自定义堆栈很好地模拟了函数递归的行为。
有一个潜在缺点:理论上,像这样的字典
{1: None, 2: {3: None, 4: None}, 5: None}
应该展平为[1, 2, 3, 4, 5]
,而此方法将给出[1, 2, 5, 3, 4]
。这就像在图形上进行DFS搜索还是BFS搜索。
但是,由于字典是无序的,所以这不是大问题(除非您使用的是collections.OrderedDict
),这就是为什么我说这是一个潜力缺点。
答案 2 :(得分:-1)
如果您想不进行递归操作,那是不可能的。
因此,这里是RecursionError的解决方案。
基于doc of python.
您可以使用sys.getrecursionlimit()
来查看递归限制。您也可以使用sys.setrecursionlimit()
来设置上限。