Convertendo uma lista aninhada de dicionário em Python

Yehui Ele:

Eu gostaria de converter uma lista aninhada de dicionário em uma subestrutura. E encontrar uma maneira robusta para fazê-lo. A estrutura:

nested_list = [
  {
     "id" : "fruit",
     "name" : "apple"
  },
  {
     "name": "fruit"
  },
  {
     "id" : "fruit",
     "name" : "grape"
  },
  {
     "id" : "fruit",
     "name" : "pineapple"
  },
  {
     "name": "vehicle"
  },
  {
    "id" : "vehicle",
     "name": "car"
  },
  {
    "id" : "car",
     "name": "sedan"
  },
] 

Para dentro:

{
  "vehicle": {
    "car": {
        "sedan" : {}
     }
  },
  "fruit" : {
     "apple": {},
    "grape": {},
    "pineapple": {}
  }
}

Note-se que, neste caso, pode ir dois níveis para baixo. Mas Ele pode ir de três, no fundo, também. Por exemplo uma entrada adicional:

{ 
   "id" : "sedan", 
   "name": "mini sedan" 
}

A minha abordagem até agora é:

for category in nested_list:
    if 'id' not in category:
        d[category['name']] = {}

for category in nested_list:
    if 'id' in category and category['id'] in d:
        d[category['id']][category['name']] = {}
    elif 'id' in category and category['id'] not in d:
        for k, v in d.items():
            if category['id'] in v:
                d[k][category['id']] = {category['name']: {}}
    # If there are not top level key then do nothing
    else:
        pass

Ele funciona neste caso. O problema é que não é o suficiente robusta. Estou pensando recursão, mas incapaz de quebrá-la. Pode alguém ajudar? Obrigado

Boseong Choi:

Solução

Você pode usar collections.defaultdicte dict.setdefault:

from collections import defaultdict

nested_list = [
    {
        "id": "fruit",
        "name": "apple"
    },
    {
        "name": "fruit"
    },
    {
        "id": "fruit",
        "name": "grape"
    },
    {
        "id": "fruit",
        "name": "pineapple"
    },
    {
        "name": "vehicle"
    },
    {
        "id": "vehicle",
        "name": "car"
    },
    {
        "id": "car",
        "name": "sedan"
    },
    {
        "id": "sedan",
        "name": "mini sedan"
    },
]

working_dict = defaultdict(dict)
result_dict = {}

for item in nested_list:
    name = item['name']
    if 'id' in item:
        id_ = item['id']
        working_dict[id_].setdefault(name, working_dict[name])
    else:
        result_dict[name] = working_dict[name]
print(working_dict)
print(result_dict)

resultado:

defaultdict(<class 'dict'>, {'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'apple': {}, 'grape': {}, 'pineapple': {}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}, 'car': {'sedan': {'mini sedan': {}}}, 'sedan': {'mini sedan': {}}, 'mini sedan': {}})
{'fruit': {'apple': {}, 'grape': {}, 'pineapple': {}}, 'vehicle': {'car': {'sedan': {'mini sedan': {}}}}}

Explicação

  • A idéia: dicté mutável.
  • working_dicté a tabela de referência para todos os "id"s.
  • Se não existe tal id, cadastre-se {}para ele.
  • E registrar elementos sem idcampo, como elementos de raiz para result_dict.

Acrescentar

Se você não quiser usar collections.defaultdict, você só pode usar dict.setdefault. Mas é mais detalhado.

working_dict = {}
result_dict = {}

for item in nested_list:
    name = item['name']
    if 'id' in item:
        id_ = item['id']
        working_dict.setdefault(id_, {}).setdefault(name, working_dict.setdefault(name, {}))
    else:
        result_dict[name] = working_dict.setdefault(name, {})
print(result_dict)

Acho que você gosta

Origin http://10.200.1.11:23101/article/api/json?id=387475&siteId=1
Recomendado
Clasificación