当嵌套字典只有一个元素时,减少它们的级别

2024-04-25 05:56:23 发布

您现在位置:Python中文网/ 问答频道 /正文

当一个节点有1个元素时,我需要通过将内键附加到上键来减少字典的嵌套级别

例如:

鉴于这本词典:

{'A': {'a': {'1': {}}},
 'B': {'b': {'2': {}},
       'c': {'3': {'x': {}}},
       'd': {},
       'e': {'0': {},
             '1': {},
            },
       },
}

我需要返回:

{'A a 1': {},
 'B': {'b 2': {},
       'c 3 x': {},
       'd': {},
       'e': {'0': {},
             '1': {},
            },
       },
 }

对于任何级别,它都应该是通用的,并且最后一个元素始终是空的dict


Tags: 元素字典节点级别dict本词典内键上键
2条回答

您可以首先展平结构以检索所有路径,然后使用collections.defaultdict重新构建它:

import collections
data = {'A': {'a': {'1': {}}}, 'B': {'b': {'2': {}}, 'c': {'3': {'x': {}}}, 'd': {}, 'e': {'0': {}, '1': {}}}}
def flatten(d, c = []):
  for a, b in d.items():
     if not b:
        yield (c+[a], b)
     else:
        yield from flatten(b, c +[a])

def compress(d):
   _d, r = collections.defaultdict(list), {}
   for [a, *b], c in d:
     _d[a].append((b, c))
   for a, b in _d.items():
      val = compress(b) if len(b) > 1 and all(j for j, _ in b) else b[0][-1]
      r[a if len(b) > 1 else a+' '+' '.join(b[0][0])] = val
   return r

print(compress(list(flatten(data))))

输出:

{'A a 1': {}, 
 'B': {'b 2': {}, 
       'c 3 x': {}, 
       'd ': {}, 
       'e': {'0 ': {}, 
             '1 ': {}}
       }
 }

我相信这个递归函数适用于您的示例:

def flatten_keys(key_so_far = '', d={}):
    if len(d) > 1:
        sub_dict = {}
        for (k,v) in d.items():
            sub_dict.update(flatten_keys(k, v))
        return {key_so_far: sub_dict} if key_so_far else sub_dict
    elif d == {}:
        return {key_so_far: {}}
    else:
        k,v = list(d.items())[0]
        key_so_far += (' ' if key_so_far else '') + k
        return(flatten_keys(key_so_far, v))

input_d = {'A': {'a': {'1': {}}},
 'B': {'b': {'2': {}},
       'c': {'3': {'x': {}}},
       'd': {},
       'e': {'0': {},
             '1': {},
            },
       },
}

flatten_keys(input_d)

# {'A a 1': {}, 'B': {'b 2': {}, 'c 3 x': {}, 'd': {}, 'e': {'0': {}, '1': {}}}}

相关问题 更多 >