【问题标题】:How can I unflatten a list of dictionaries in python 2.7 as in the example?如示例所示,如何在 python 2.7 中展开字典列表?
【发布时间】:2021-07-01 16:41:19
【问题描述】:

我正在使用 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)

我不明白为什么我在输出中丢失了信息(结果没有显示所有类别)。

【问题讨论】:

  • 如果您还不知道,Python 2 的所有版本都是deprecated as of January 1st, 2020 并且将不再获得支持或安全更新。强烈建议您尽可能迁移到 Python 3。
  • macrocategory 和 microcategory 给出 unboundlocalerror,赋值前引用
  • 是的,谢谢,但我在 2.7 中需要它
  • 是的,对不起。我已经插入了丢失的部分代码
  • 我可以把 tools.dump2 和 d_attributes (undefined) 注释掉吗?

标签: python list python-2.7 dictionary


【解决方案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'}]
    

    【讨论】:

      猜你喜欢
      • 2021-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多