解析和创建嵌套字典

时间:2019-08-10 21:58:26

标签: python python-3.x dictionary

我想创建一个包含字典嵌套结构的字典,例如波纹管:


{
  "Jaque": {
    "ES": {
      "Madrid": [
        {
          "experience": 9
        }
      ]
    },
    "FR": {
      "Lyon": [
        {
          "experience": 11.4
        }
      ],
      "Paris": [
        {
          "experience": 20
        }
      ]
    }
  },
  "James": {
    "UK": {
      "London": [
        {
          "experience": 10.9
        }
      ]
    }
  },
  "Henry": {
    "UK": {
      "London": [
        {
          "experience": 15
        }
      ]
    }
  },
  "Joe": {
    "US": {
      "Boston": [
        {
          "experience": 100
        }
      ]
    }
  }
}
}

我的输入是以下格式的字典的列表:

c = [{
    "country": "US",
    "city": "Boston",
    "name": "Joe",
    "experience": 100
  },
  {
    "country": "FR",
    "city": "Paris",
    "name": "Jaque",
    "experience": 20
  },
  {
    "country": "FR",
    "city": "Lyon",
    "name": "Jaque",
    "experience": 11.4
  },
  {
    "country": "ES",
    "city": "Madrid",
    "name": "Jaque",
    "experience": 9
  },
  {
    "country": "UK",
    "city": "London",
    "name": "Henry",
    "experience": 15
  },
  {
    "country": "UK",
    "city": "London",
    "name": "James",
    "experience": 10.9
  }
]

我的第一种方法是逐步创建嵌套字典:


dd = dict.fromkeys([i.get("name") for i in c],defaultdict(dict))

#will create
# dd = {'Joe': defaultdict(<class 'dict'>, {}), 'Jaque': defaultdict(<class 'dict'>, {}), 'James': defaultdict(<class 'dict'>, {}), 'Henry': defaultdict(<class 'dict'>, {})}

for i in dd:
     for j in c:
         #verify if name from d is in dict j 
         if i in j.values():
             dd[i]=dict(zip([a.get("country") for a in c if i in a.values() ],[b.get("city") for b in c if i in b.values() ]))

# dd will become 
#{'Joe': {'US': 'Boston'}, 'Jaque': {'FR': 'Lyon', 'ES': 'Madrid'}, 'Henry': {'UK': 'London'}, 'James': {'UK': 'London'}}

现在我无法找到一种创建/更新dict dd嵌套结构的方法。有没有更动态的方法来创建字典?谢谢

2 个答案:

答案 0 :(得分:1)

您可以使用itertools.groupby来组织列表,使其与预期的输出类似,然后循环转换为字典。

from itertools import groupby
from operator import itemgetter

data = [{"country": "US", "city": "Boston", "name": "Joe", "experience": 100 }, {"country": "FR", "city": "Paris", "name": "Jaque", "experience": 20 }, {"country": "FR", "city": "Lyon", "name": "Jaque", "experience": 11.4 }, {"country": "ES", "city": "Madrid", "name": "Jaque", "experience": 9 }, {"country": "UK", "city": "London", "name": "Henry", "experience": 15 }, {"country": "UK", "city": "London", "name": "James", "experience": 10.9 } ]

result = {}
for key, values in groupby(sorted(data, key=itemgetter('name')), key=itemgetter('name')):
    result[key] = {
        v['country']: {v['city']: [{'experience': v['experience']}]} for v in values
        }

print(result)
# {'Henry': {'UK': {'London': [{'experience': 15}]}}, 'James': {'UK': {'London': [{'experience': 10.9}]}}, 'Jaque': {'FR': {'Lyon': [{'experience': 11.4}]}, 'ES': {'Madrid': [{'experience': 9}]}}, 'Joe': {'US': {'Boston': [{'experience': 100}]}}}

答案 1 :(得分:1)

您可以对itertools.groupby使用递归:

from itertools import groupby
def group(d, keys = None):
   key, *keys = keys
   new_d = {a:list(b) for a, b in groupby(sorted(d, key=lambda x:x[key]), key=lambda x:x[key])}
   t = {a:[{c:d for c, d in k.items() if c != key} for k in b] for a, b in new_d.items()}
   return {a:group(b, keys) if not all(len(i) == 1 for i in b) else b for a, b in t.items()}

result = group(data, keys = ['name', 'country', 'city', 'experience'])

import json
print(json.dumps(result, indent=4)))

输出:

{
  "Henry": {
    "UK": {
        "London": [
            {
                "experience": 15
            }
        ]
    }
  },
  "James": {
    "UK": {
        "London": [
            {
                "experience": 10.9
            }
        ]
    }
  },
  "Jaque": {
    "ES": {
        "Madrid": [
            {
                "experience": 9
            }
        ]
    },
    "FR": {
        "Lyon": [
            {
                "experience": 11.4
            }
        ],
        "Paris": [
            {
                "experience": 20
            }
        ]
    }
  },
  "Joe": {
    "US": {
        "Boston": [
            {
                "experience": 100
            }
        ]
     }
  }
}