简体   繁体   English

如何根据值删除列表的嵌套字典中的键

[英]How to delete keys in a nested dictionary of lists based on the values

I am working on a file representing a tree-like structure very similar to flare.json which is known for D3.js community. 我正在处理一个表示类似于flare.json的树状结构的文件,该文件以D3.js社区而闻名。 What's the best way to delete all the leaves of the tree in python? 在python中删除树上所有叶子的最佳方法是什么? In other words, I want to remove all the keys that don't have a 'children' key in their value. 换句话说,我要删除所有键中没有“儿童”键的键。

example : 例如:

{
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster", "size": 3938},
      {"name": "CommunityStructure", "size": 3812},
      {"name": "HierarchicalCluster", "size": 6714},
      {"name": "MergeEdge", "size": 743}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality", "size": 3534},
      {"name": "LinkDistance", "size": 5731},
      {"name": "MaxFlowMinCut", "size": 7840},
      {"name": "ShortestPaths", "size": 5914},
      {"name": "SpanningTree", "size": 3416}
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker", "size": 7074}
     ] ...

which should become: 应该变成:

{
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
    },
    {
     "name": "graph",
    },
    {
     "name": "optimization",

     ] ...

In other words, I'm just cutting the leaves of the tree. 换句话说,我只是在砍树的叶子。 In a children list is empty, it should be removed. 在子级列表为空时,应将其删除。

I tried this only to remove the keys and it did not work: 我尝试这样做只是为了删除密钥,但是它不起作用:

def deleteLeaves(pTree):
    if pTree.has_key('children'):
        for child in pTree['children']:
            deleteLeaves(child)
    else:
        del pTree

This seems to approximate what you want: 这似乎与您想要的近似:

def pruneLeaves(obj):

  if isinstance(obj, dict):
    isLeaf = True
    for key in obj.keys():
      if key == 'children': isLeaf = False
      if pruneLeaves(obj[key]): del obj[key]
    return isLeaf

  elif isinstance(obj, list):
    leaves = []
    for (index, element) in enumerate(obj):
      if pruneLeaves(element): leaves.append(index)
    leaves.reverse()
    for index in leaves: obj.pop(index)
    return not bool(obj)

  else:  # String values look like attributes in your dict, so never prune them
    return False

Tested with a truncated sample of your data: 使用截断的数据样本进行了测试:

data = {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster", "size": 3938},
      {"name": "CommunityStructure", "size": 3812},
      {"name": "HierarchicalCluster", "size": 6714},
      {"name": "MergeEdge", "size": 743}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality", "size": 3534},
      {"name": "LinkDistance", "size": 5731},
      {"name": "MaxFlowMinCut", "size": 7840},
      {"name": "ShortestPaths", "size": 5914},
      {"name": "SpanningTree", "size": 3416}
     ]
    }
   ]
  }
  ]
}

pruneLeaves(data)
print data

And got these results: 并得到以下结果:

{'name': 'flare', 'children': [{'name': 'analytics', 'children': [{'name': 'cluster'}, {'name': 'graph'}]}]}

I just edited the answer of @rchang to fix deletion of lists other than children . 我只是编辑了@rchang的答案 ,以解决删除除children以外的列表的问题。

def pruneLeaves(self,obj):
    if isinstance(obj, dict):
        isLeaf = True
        for key in obj.keys():
            if key=='children': 
                isLeaf = False
                if self.pruneLeaves(obj[key]): del obj[key]
        return isLeaf

    elif isinstance(obj, list) :
        leaves = []
        for (index, element) in enumerate(obj):
          if self.pruneLeaves(element): leaves.append(index)
        leaves.reverse()
        for index in leaves: obj.pop(index)
        return not bool(obj)
    else:  # String values look like attributes in your dict, so never prune them
        return False

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM