#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'}]