所以,我已经阅读了很多关于在Python中递归地展平字典的帖子。没有(保存一个)接近我正在寻找的东西。首先,我要完成的一个简单示例:
具有混合条目的示例字典:(键和值将始终为混合类型)
{'a': [{'b': {'c': 'd', 'e': 'f', 'g': 'h',
'i': {'j': {'k': ['l'], 'm': 'n'}},
'o': {'p': {'q': ['r', 's' ], 't': 'u'}}
}
}]
}
期望的输出:
{'a/b/c/d',
'a/b/e/f',
'a/b/g/h',
'a/b/i/j/k/l',
'a/b/i/j/m/n',
'a/b/o/p/q/r',
'a/b/o/p/q/s',
'a/b/o/p/t/u'}
该功能应该(理论上)也适用于列表。
为了解释一下我正在做什么,我试图通过Mac plist进行搜索,其他尝试按键或值进行搜索最多也是不稳定的。为了弥补,我想尝试一种不同的方法。将字典转换为“路径”列表,然后只搜索路径。
我尝试了自己(并且部分成功)然后我找到了一个更好的解决方案:
def flatten(structure, key="", path="", flattened=None):
if flattened is None:
flattened = {}
if type(structure) not in(dict, list):
flattened[((path + "/") if path else "") + key] = structure
elif isinstance(structure, list):
for i, item in enumerate(structure):
flatten(item, "", "/".join(filter(None,[path,key])), flattened)
else:
for new_key, value in structure.items():
flatten(value, new_key, "/".join(filter(None,[path,key])), flattened)
return flattened
这很有效,但有一些不受欢迎的影响。首先,输出如下:
{'a/b/c' : 'd',
'a/b/e' : 'f',
'a/b/g' : 'h',
'a/b/i/j/k/': 'l',
'a/b/i/j/m' : 'n',
'a/b/o/p/q/': 's',
'a/b/o/p/t' : 'u'}
这将返回键/值对的字典。我宁愿有一个字符串路径列表。其次,更重要的是,你会注意到,脚本已经剥离了值为列表的值。仅附加列表的最后一项。
'a/b/o/p/q/': 's' # there should be another entry with 'r' as the value.
我花了相当多的时间摆弄输出并试图完全解决问题无济于事。它可能只是我对Python的理解,但我想要的输出应该是可能的。
我尽量不提问题,除非我已经用尽了选项而且我在这里。请不要将其标记为重复,因为其他问题并不完全符合我要求的目标。
感谢您的时间和帮助/指导。
答案 0 :(得分:2)
Python 2.7:
def flatten(structure):
if isinstance(structure, basestring):
return [structure]
ret = []
if isinstance(structure, list):
for v in structure:
ret.extend(flatten(v))
elif isinstance(structure, dict):
for k, v in structure.items():
ret.extend(k + '/' + f for f in flatten(v))
return ret
print sorted(flatten(structure))
输出:
['a/b/c/d', 'a/b/e/f', 'a/b/g/h', 'a/b/i/j/k/l', 'a/b/i/j/m/n', 'a/b/o/p/q/r', 'a/b/o/p/q/s', 'a/b/o/p/t/u']
或者,如果您不关心订单,可以print flatten(structure)
。
答案 1 :(得分:1)
以下是我在Python 3.3 +中的表现:
def flatten(exp):
def sub(exp, res):
if type(exp) == dict:
for k, v in exp.items():
yield from sub(v, res+[k])
elif type(exp) == list:
for v in exp:
yield from sub(v, res)
else:
yield "/".join(res+[exp])
yield from sub(exp, [])
测试:
l={'a': [{'b': {'c': 'd', 'e': 'f', 'g': 'h',
'i': {'j': {'k': ['l'], 'm': 'n'}},
'o': {'p': {'q': ['r', 's' ], 't': 'u'}}
}
}]
}
for i in sorted(flatten(l)):
print(i)
产量
a/b/c/d
a/b/e/f
a/b/g/h
a/b/i/j/k/l
a/b/i/j/m/n
a/b/o/p/q/r
a/b/o/p/q/s
a/b/o/p/t/u
编辑对Python 2的翻译很简单:
def flatten(exp):
def sub(exp, res):
if type(exp) == dict:
for k, v in exp.items():
for r in sub(v, res+[k]):
yield r
elif type(exp) == list:
for v in exp:
for r in sub(v, res):
yield r
else:
yield "/".join(res+[exp])
for r in sub(exp, []):
yield r
然后
>>> for i in sorted(flatten(l)):
... print i
...
a/b/c/d
a/b/e/f
a/b/g/h
a/b/i/j/k/l
a/b/i/j/m/n
a/b/o/p/q/r
a/b/o/p/q/s
a/b/o/p/t/u