我有一个具有各种“深度”的字典数据结构。 以“深度”为例,我的意思是: 当深度为1时,dict将如下:
{'str_key1':int_value1, 'str_key2:int_value2}
当深度为2时,dict将如下:
{'str_key1':
{'str_key1_1':int_value1_1,
'str_key1_2':int_value1_2},
'str_key2':
{'str_key2_1':int_value2_1,
'str_key2_2':int_value2_2} }
等等。
当我需要处理数据时,现在我正在这样做:
def process(keys,value):
#do sth with keys and value
pass
def iterate(depth,dict_data):
if depth == 1:
for k,v in dict_data:
process([k],v)
if depth == 2:
for k,v in dict_data:
for kk,vv, in v:
process([k,kk],v)
if depth == 3:
.........
当深度 n 时,我需要 n for循环。由于深度可以达到10,我想知道是否有更动态的方法来进行迭代而不必写出所有if和for子句。
感谢。
答案 0 :(得分:4)
我不确定为什么每个人都在考虑递归(或递归消除) - 我只是执行depth
个步骤,每个步骤通过向下扩展它来重建列表。
E.g:
def itr(depth, d):
cp = [([], d)]
for _ in range(depth):
cp = [(lk+[k], v) for lk, d in cp for k, v in d.items()]
for lk, ad in cp:
process(lk, ad)
如果为了教学目的需要使其更具可读性,使用更长的标识符和更低的代码密度易于“扩展”,但我认为逻辑很简单,可能不需要这样的处理(并且,为了它自己的缘故,冗长也有它的缺点; - )。
例如:
d = {'str_key1':
{'str_key1_1':'int_value1_1',
'str_key1_2':'int_value1_2'},
'str_key2':
{'str_key2_1':'int_value2_1',
'str_key2_2':'int_value2_2'} }
def process(lok, v):
print lok, v
itr(2, d)
打印
['str_key2', 'str_key2_2'] int_value2_2
['str_key2', 'str_key2_1'] int_value2_1
['str_key1', 'str_key1_1'] int_value1_1
['str_key1', 'str_key1_2'] int_value1_2
(如果需要某些特定顺序,当然可以在cp
)执行适当的排序。
答案 1 :(得分:3)
显而易见的答案是使用递归。但是,你可以在这里使用Python来做一些平滑的字体。这仍然是从根本上递归的 - 我们只是实现自己的堆栈。
def flatten(di):
stack = [di]
while stack:
e = stack[-1]
for k, v in e.items():
if isinstance(v, dict):
stack.append(v)
else:
yield k, v
stack.remove(e)
然后,您可以执行以下操作:
for k, v in flatten(mycomplexdict):
process(k, v)
答案 2 :(得分:2)
递归是你的朋友:
def process(keys,value):
#do sth with keys and value
pass
def iterate(depth, dict_data):
iterate_r(depth, dict_data, [])
def iterate_r(depth, data, keys):
if depth == 0:
process(keys, data)
else:
for k,v in dict_data.items():
iterate_r(depth-1, v, keys+[k])
答案 3 :(得分:2)
Reusive,请记住python只能递归1000次:
def process(key, value):
print key, value
def process_dict(dict, callback):
for k, v in dict.items():
if hasattr(v, 'items'):
process_dict(v, callback)
else:
callback(k, v)
d = {'a': 1, 'b':{'b1':1, 'b2':2, 'b3':{'bb1':1}}}
process_dict(d, process)
打印:
a 1
b1 1
b2 2
bb1 1
答案 4 :(得分:1)
假设您想要一个固定的深度(大多数其他答案似乎假设您要递归到最大深度),并且您需要保留原始问题中的路径,这是最直接的解决方案:
def process_dict(d, depth, callback, path=()):
for k, v in d.iteritems():
if depth == 1:
callback(path + (k,), v)
else:
process_dict(v, depth - 1, callback, path + (k,))
这是一个实际的例子:
>>> a_dict = {
... 'dog': {
... 'red': 5,
... 'blue': 6,
... },
... 'cat': {
... 'green': 7,
... },
... }
>>> def my_callback(k, v):
... print (k, v)
...
>>> process_dict(a_dict, 1, my_callback)
(('dog',), {'blue': 6, 'red': 5})
(('cat',), {'green': 7})
>>> process_dict(a_dict, 2, my_callback)
(('dog', 'blue'), 6)
(('dog', 'red'), 5)
(('cat', 'green'), 7)