2011-05-17 56 views
2

我有这个多维字典:的Python - Unflatten字典

a = {'a' : 'b', 'c' : {'d' : 'e'}} 

和书写简单的功能扁平化是字典:

def __flatten(self, dictionary, level = []): 
    tmp_dict = {} 
    for key, val in dictionary.items(): 
     if type(val) == dict: 
      tmp_dict.update(self.__flatten(val, level + [key])) 
     else: 
      tmp_dict['.'.join(level + [key])] = val 
    return tmp_dict 

通话用字典a这个功能我在结果得到后:

{'a' : 'b', 'c.d' : 'e'} 

现在,在对这个扁平的字典作出几个指示后,我需要建立新的,从这个扁平的多维词典。例如:

>> unflatten({'a' : 0, 'c.d' : 1)) 
{'a' : 0, 'c' : {'d' : 1}} 

我唯一的问题是我不具备的功能unflatten :)
任何人都可以在这方面帮助?我不知道该怎么做。

编辑:

又如:

{'a' : 'b', 'c.d.e.f.g.h.i.j.k.l.m.n.o.p.r.s.t.u.w' : 'z'} 

后应unflatten:

{'a': 'b', 'c': {'d': {'e': {'f': {'g': {'h': {'i': {'j': {'k': {'l': {'m': {'n': {'o': {'p': {'r': {'s': {'t': {'u': {'w': 'z'}}}}}}}}}}}}}}}}}}} 

而另:

{'a' : 'b', 'c.d' : 'z', 'c.e' : 1} 

要:

{'a' : 'b', 'c' : {'d' : 'z', 'e' : 1}} 

这大大增加了工作的难度,我知道。这就是为什么我有这个问题,并发现小时无解..

+0

我真的不能明白为什么' 'C':{ 'd': 'E'}''变成 'CD': 'e'',如果你有'' C ':{'f':'g','d':'e'}' – neurino 2011-05-17 22:00:49

+0

Then'{'c':{'f':'g','d':'e'}}'' 'cf':'g','cd':'e'}':) – Galmi 2011-05-17 22:12:39

回答

6
def unflatten(dictionary): 
    resultDict = dict() 
    for key, value in dictionary.iteritems(): 
     parts = key.split(".") 
     d = resultDict 
     for part in parts[:-1]: 
      if part not in d: 
       d[part] = dict() 
      d = d[part] 
     d[parts[-1]] = value 
    return resultDict 
+0

这个实现比我的更好,因为它处理输入{'a':'b','c.d.e':1}和任何更深的嵌套(更多点)。我害怕降低自己的答案...不知道会发生什么。 ;) – 2011-05-17 22:05:39

+0

它完全按照我的需要工作。谢谢你,你救了我一整夜的思考:) – Galmi 2011-05-17 22:35:29

1

作一个粗略的草稿(可以使用在变量名的选择稍有起色,也许鲁棒性,但它工作在给出的例子):

def unflatten(d): 
    result = {} 
    for k,v in d.iteritems(): 
     if '.' in k: 
      k1, k2 = k.split('.', 1) 
      v = {k2: v} 
      k = k1 
     result[k] = v 
    return result 
+0

Dangit!即使我有足够的人承认它不如另一个好(Messa在这种情况下),我也不能低估自己的答案。 – 2011-05-17 22:08:39

+0

你可以删除它,我认为;) – 2011-05-17 22:19:12

2
from collections import defaultdict 
def unflatten(d): 
    ret = defaultdict(dict) 
    for k,v in d.items(): 
     k1,delim,k2 = k.partition('.') 
     if delim: 
      ret[k1].update({k2:v}) 
     else: 
      ret[k1] = v 
    return ret 
+0

使用递归+1,但不正确:例如''{'a.b':0,'a.c':1}''将返回''{'a':{'c':1}}''可以使用''ret [k1] .update(...)''代替。 – 2011-05-17 22:17:28

+0

@Lucasmus,是的,我现在把它改回原来的答案。我暂时认为它可以简化 – 2011-05-17 22:20:42