Как я могу удалить список словарей в python 2.7, как в примере?

#python #list #python-2.7 #dictionary

Вопрос:

Я использую python 2.7. У меня есть входные данные, которые представляют собой список словарей. В моей системе пользователь может добавлять макрокатегории. Эти макрокатегории могут содержать 0 или более категорий. А категории, содержащиеся в макрокатегориях, могут содержать 0 или более микрокатегорий. Макрокатегории, категории и микрокатегории уникальны. Входной список словарей уже упорядочен сначала по макрокатегориям, затем по категориям и последним по микрокатегориям.

     input = [{
      'desc_category': 'category1',
      'desc_macrocategory': 'macrocategory1',
      'desc_microcategory': 'microcategory1',
      'id_category': '1',
      'id_macrocategory': '1',
      'id_microcategory': '1',
      },
     {
      'desc_category': 'category2',
      'desc_macrocategory': 'macrocategory1',
      'desc_microcategory': None,
      'id_category': '2',
      'id_macrocategory': '1',
      'id_microcategory': '0',

      },
     {
      'desc_category': 'category5',
      'desc_macrocategory': 'macrocategory1',
      'desc_microcategory': None,
      'id_category': '5',
      'id_macrocategory': '1',
      'id_microcategory': '0',
      },

     {
      'desc_category': 'category21',
      'desc_macrocategory': 'macrocategory2',
      'desc_microcategory': None,
      'id_category': '21',
      'id_macrocategory': '2',
      'id_microcategory': '0',
      },
     {
      'desc_category': 'category28',
      'desc_macrocategory': 'macrocategory2',
      'desc_microcategory': None,
      'id_category': '28',
      'id_macrocategory': '2',
      'id_microcategory': '0',
      },

     {
      'desc_category': 'category31',
      'desc_macrocategory': 'macrocategory3',
      'desc_microcategory': 'microcategory71',
      'id_category': '31',
      'id_macrocategory': '3',
      'id_microcategory': '71',
     },
     {
      'desc_category': 'category31',
      'desc_macrocategory': 'macrocategory3',
      'desc_microcategory': 'microcategory72',
      'id_category': '31',
      'id_macrocategory': '3',
      'id_microcategory': '72',
     },
     {
      'desc_category': None,
      'desc_macrocategory': 'macrocategory4',
      'desc_microcategory': None,
      'id_category': '0',
      'id_macrocategory': '4',
      'id_microcategory': '0',
      }
    ]
 

результат должен быть:

     output = [
        {   'desc_macrocategory': 'macrocategory1',
            'id_macrocategory': 1,
            'categories': [
                {   'desc_category': 'category1',
                    'id_category': 1,
                    'microcategories': [
                        {   'desc_microcategory': 'microcategory1',
                            'id_microcategory': 1
                        }
                    ]
                },
                {   'desc_category': 'category2',
                    'id_category': 2,
                    'microcategories': []
                },
        
                {   'desc_category': 'category5',
                    'id_category': 5,
                    'microcategories': []
                }
            ]
        },      
        {   'desc_macrocategory': 'macrocategory2',
            'id_macrocategory': 2,
            'categories': [
                {   'desc_category': 'category21',
                    'id_category': 21,
                    'microcategories': []
                },
                {   'desc_category': 'category28',
                    'id_category': 28,
                    'microcategories': []
                }
            ]
        },      
        {   'desc_macrocategory': 'macrocategory3',
            'id_macrocategory': 3,
            'categories': [
                {   'desc_category': 'category31',
                    'id_category': 31,
                    'microcategories': [
                        {   'desc_microcategory': 'microcategory71',
                            'id_microcategory': 71
                        },
                        {   'desc_microcategory': 'microcategory72',
                            'id_microcategory': 72
                        }
                    ]
                }
            ]
        },  
        {   'desc_macrocategory': 'macrocategory4',
            'id_macrocategory': 4,  
            'categories': []
        }
    ]
 

Я пробовал это, но результат неверен, и я не знаю, в чем проблема. Или если есть лучший способ получить желаемый результат:

     output=[]
    macrocategory = '-'
    category = '-'
    d_macro = {}
    d_category = {}
    l_cat = []
    l_mic = []
    for dict_info in input:
        if macrocategory != int(dict_info['id_macrocategory']):
            macrocategory = int(dict_info['id_macrocategory'])
            category = '-' 
            if d_macro:
                d_category.update({'microcategories': l_mic})
                if d_category['id_category'] != 0:
                    l_cat.append(d_category)
                d_category = {}
                d_macro.update({'categories': l_cat})
                d_attributes['macro_categories'].append(d_macro)
                l_cat = []
                l_mic = []

            d_macro = {
                'id_macrocategory': int(dict_info['id_macrocategory']),
                'desc_macrocategory': dict_info['desc_macrocategory'],
                'categories': []
            }
        
        if category != int(dict_info['id_category']):
            category = int(dict_info['id_category'])
            if d_category:
                d_category.update({'microcategories': l_mic})
                if d_category['id_category'] != 0:
                    l_cat.append(d_category)
                    
                l_mic = []

            d_category = {
                'id_category': int(dict_info['id_category']),
                'desc_category': dict_info['desc_category'],
                'microcategories': []
            }

        d_micro = {
            'id_microcategory': int(dict_info['id_microcategory']),
            'desc_microcategory': dict_info['desc_microcategory'],
        }

        if d_micro['id_microcategory'] != 0:
            l_mic.append(d_micro)

    # for the last one
    d_category.update({'microcategories': l_mic})
    d_macro.update({'categories': l_cat})
    output.append(d_macro)
 

Я не могу понять, почему я теряю информацию в выводе (результат показывает мне не все категории).

Комментарии:

1. Если вы еще не в курсе, все версии Python 2 устарели с 1 января 2020 года и больше не будут получать обновления поддержки или безопасности. Настоятельно рекомендуется перейти на Python 3, если это вообще возможно.

2. макрокатегория и микрокатегория дают неограниченную ошибку, на которую ссылаются перед назначением

3. да, спасибо, но мне это нужно в 2.7

4. да, извините. Я уже вставил ту часть кода, которая отсутствовала

5. могу ли я просто прокомментировать инструменты.dump2 и атрибуты d_attributes (не определены)?

Ответ №1:

Не пытайтесь делать все сразу, создайте пользовательский синтаксический анализатор, который создает для вас объекты, которые могут представлять то, что вы действительно хотите, а затем повторите свой список словарей, используя блоки, чтобы сделать то, что вы хотите.

Соберите все отображаемые имена в диктант

 NAMES = {
    "desc": {
        "micro": "desc_macrocategory",
        "mid":   "desc_category",
        "macro": "desc_microcategory",
    },
    "id": {
        "micro": "id_macrocategory",
        "mid":   "id_category",
        "macro": "id_microcategory",
    },
    "category_listing": {
        "macro": "categories",
        "mid":   "microcategories",
        # no micro field
    }
}
 

создайте пользовательский объект для своих категорий и для создания объектов

 def Category():
    def __init__(self, name, category_level):
        self.category_name  = name
        self.category_level = category_level
        self.category_id    = None
        self.members = {}

    def export(self):
        # consider ensuring some needed members are non-None?
        d = {   # get field names from mapping
            NAMES["desc"][self.category_level]: self.category_name,
            NAMES["id"][self.category_level]:   self.category_id,
        }
        if self.category_level != "micro":  # maybe [], but not for micro
            d[NAMES["category_listing"][self.category_level]] = [c.export() for c in self.members.values()]
        return d
 

проанализируйте их

 def category_parser(macro_categories, input_block):
    try:
        name_macro = input_block["desc_macrocategory"]
    except Exception:
        "whatever should happen if this fails"

    try:  # get the macro category or create a new one
        macro = macro_categories[name_macro]
    except KeyError:  # create a new Category for the macro name
        macro = Category(name_macro, "macro")
        macro_categories[category.name] = macro
        macro.category_id = input_block["id_macrocategory"]

    name_mid = input_block.get("desc_category")
    if name_mid:
        try:
            mid = macro.members["name_mid"]
        except KeyError:
            mid = Category(name_mid, "mid")
            macro.members[mid.name] = mid
            mid.id = input_block.get["id_category"]  # always set?

    name_micro = input_block.get("desc_microcategory")
    if name_micro:
        if not mid:
            raise ValueError("no middle member for micro member to reference")
        try:
            micro = mid.members["name_micro"]
        except KeyError:
            micro = Category(name_mid, "name_micro")
            mid.members[name_micro.name] = name_micro
            micro.id = input_block.get("id_microcategory")  # always set?
 

проанализируйте их все, а затем отобразите

 macro_categories = {}
for input_block in collection_of_dictionaries:  # don't clobber `input`
    category_parser(macro_categories, input_block)

{category.export() for category in macro_categories.values()}
 

Возможно , его можно использовать defaultDict() вместо try/except KeyError , но я помню, что это более неудобно, чем того стоит.

Ответ №2:

Вы можете попробовать этот код, чтобы удалить список (предположим, что список отсортирован по id_macrocategory ):

 lst = [
    {
        "desc_category": "category1",
        "desc_macrocategory": "macrocategory1",
        "desc_microcategory": "microcategory1",
        "id_category": "1",
        "id_macrocategory": "1",
        "id_microcategory": "1",
    },
    {
        "desc_category": "category2",
        "desc_macrocategory": "macrocategory1",
        "desc_microcategory": None,
        "id_category": "2",
        "id_macrocategory": "1",
        "id_microcategory": "0",
    },
    {
        "desc_category": "category5",
        "desc_macrocategory": "macrocategory1",
        "desc_microcategory": None,
        "id_category": "5",
        "id_macrocategory": "1",
        "id_microcategory": "0",
    },
    {
        "desc_category": "category21",
        "desc_macrocategory": "macrocategory2",
        "desc_microcategory": None,
        "id_category": "21",
        "id_macrocategory": "2",
        "id_microcategory": "0",
    },
    {
        "desc_category": "category28",
        "desc_macrocategory": "macrocategory2",
        "desc_microcategory": None,
        "id_category": "28",
        "id_macrocategory": "2",
        "id_microcategory": "0",
    },
    {
        "desc_category": "category31",
        "desc_macrocategory": "macrocategory3",
        "desc_microcategory": "microcategory71",
        "id_category": "31",
        "id_macrocategory": "3",
        "id_microcategory": "71",
    },
    {
        "desc_category": "category31",
        "desc_macrocategory": "macrocategory3",
        "desc_microcategory": "microcategory72",
        "id_category": "31",
        "id_macrocategory": "3",
        "id_microcategory": "72",
    },
    {
        "desc_category": None,
        "desc_macrocategory": "macrocategory4",
        "desc_microcategory": None,
        "id_category": "0",
        "id_macrocategory": "4",
        "id_microcategory": "0",
    },
]


from pprint import pprint
from itertools import groupby


out = []
for v1, g1 in groupby(lst, lambda k: k["id_macrocategory"]):
    g1 = [*g1]
    out.append(
        {
            "desc_macrocategory": g1[0]["desc_macrocategory"],
            "id_macrocategory": v1,
            "categories": [],
        }
    )
    for v2, g2 in groupby(
        sorted(
            [g for g in g1 if int(g["id_category"]) != 0],
            key=lambda k: k["id_category"],
        ),
        lambda k: k["id_category"],
    ):
        g2 = [*g2]
        out[-1]["categories"].append(
            {
                "desc_category": g2[0]["desc_category"],
                "id_category": v2,
                "microcategories": [],
            }
        )
        for v3, g3 in groupby(
            sorted(
                [g for g in g2 if int(g["id_microcategory"]) != 0],
                key=lambda k: k["id_microcategory"],
            ),
            lambda k: k["id_microcategory"],
        ):
            g3 = [*g3]
            out[-1]["categories"][-1]["microcategories"].append(
                {
                    "desc_microcategory": g3[0]["desc_microcategory"],
                    "id_microcategory": v3,
                }
            )

pprint(out)
 

С принтами:

 [{'categories': [{'desc_category': 'category1',
                  'id_category': '1',
                  'microcategories': [{'desc_microcategory': 'microcategory1',
                                       'id_microcategory': '1'}]},
                 {'desc_category': 'category2',
                  'id_category': '2',
                  'microcategories': []},
                 {'desc_category': 'category5',
                  'id_category': '5',
                  'microcategories': []}],
  'desc_macrocategory': 'macrocategory1',
  'id_macrocategory': '1'},
 {'categories': [{'desc_category': 'category21',
                  'id_category': '21',
                  'microcategories': []},
                 {'desc_category': 'category28',
                  'id_category': '28',
                  'microcategories': []}],
  'desc_macrocategory': 'macrocategory2',
  'id_macrocategory': '2'},
 {'categories': [{'desc_category': 'category31',
                  'id_category': '31',
                  'microcategories': [{'desc_microcategory': 'microcategory71',
                                       'id_microcategory': '71'},
                                      {'desc_microcategory': 'microcategory72',
                                       'id_microcategory': '72'}]}],
  'desc_macrocategory': 'macrocategory3',
  'id_macrocategory': '3'},
 {'categories': [],
  'desc_macrocategory': 'macrocategory4',
  'id_macrocategory': '4'}]