如何像示例中那样在 python 2.7 中展开字典列表?
How can I unflatten a list of dictionaries in python 2.7 as in the example?
我正在使用 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)
我不明白为什么我在输出中丢失了信息(结果没有显示所有类别)。
您可以尝试使用此代码来展开列表(假设列表按 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'}]
不要尝试一次做所有事情,创建一个自定义解析器,为您创建可以代表您真正想要的对象,然后遍历您的字典列表,使用块来创建您想要的。
将所有可映射的名称收集到字典中
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
,但我记得这比它的价值更尴尬。
我正在使用 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)
我不明白为什么我在输出中丢失了信息(结果没有显示所有类别)。
您可以尝试使用此代码来展开列表(假设列表按 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'}]
不要尝试一次做所有事情,创建一个自定义解析器,为您创建可以代表您真正想要的对象,然后遍历您的字典列表,使用块来创建您想要的。
将所有可映射的名称收集到字典中
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
,但我记得这比它的价值更尴尬。