对我来说,把这个问题分成两部分是最有意义的(好吧,我第一次把这个问题读错了…)
转换
第一部分将[key, list1, list2]数据结构转换为嵌套字典:def recdict(elements):
"""Create recursive dictionaries from [k, v1, v2, ...] lists.
>>> import pprint, functools
>>> pprint = functools.partial(pprint.pprint, width=2)
>>> pprint(recdict(['a', ['b', ['x', '1'], ['y', '2']]]))
{'a': {'b': {'x': '1',
'y': '2'}}}
>>> pprint(recdict(['a', ['c', ['xx', '4'], ['gg', ['m', '3']]]]))
{'a': {'c': {'gg': {'m': '3'},
'xx': '4'}}}
"""
def rec(item):
if isinstance(item[1], list):
return [item[0], dict(rec(e) for e in item[1:])]
return item
return dict([rec(elements)])
它希望如此每个列表至少有两个元素
每个列表的第一个元素是一个键
如果列表的第二个元素是列表,那么所有后续元素也都是列表;这些元素被组合到字典中。在
最棘手的一点(至少对我来说)是意识到必须从递归函数返回一个列表,而不是从字典返回。否则,您不能组合构成某些列表的第二和第三个元素的并行列表。在
为了使它更普遍地有用(即元组和其他序列),我将改变
^{2}$
到if (isinstance(item[1], collections.Sequence)
and not isinstance(item[1], basestring)):
你也可以让它为任何iterable工作,但这需要一点重组。在
合并
第二部分合并在两个给定数据结构上运行第一个例程所产生的字典。我认为这将递归地合并没有冲突键的任何数量的字典,尽管除了这个用例之外,我并没有真正测试过它。在def mergedicts(*dicts):
"""Recursively merge an arbitrary number of dictionaries.
>>> import pprint
>>> d1 = {'a': {'b': {'x': '1',
... 'y': '2'}}}
>>> d2 = {'a': {'c': {'gg': {'m': '3'},
... 'xx': '4'}}}
>>> pprint.pprint(mergedicts(d1, d2), width=2)
{'a': {'b': {'x': '1',
'y': '2'},
'c': {'gg': {'m': '3'},
'xx': '4'}}}
"""
keys = set(k for d in dicts for k in d)
def vals(key):
"""Returns all values for `key` in all `dicts`."""
withkey = (d for d in dicts if d.has_key(key))
return [d[key] for d in withkey]
def recurse(*values):
"""Recurse if the values are dictionaries."""
if isinstance(values[0], dict):
return mergedicts(*values)
if len(values) == 1:
return values[0]
raise TypeError("Multiple non-dictionary values for a key.")
return dict((key, recurse(*vals(key))) for key in keys)