Python - 按名称附加到字典,多级 1、1.1、1.1.1、1.1.2(分层)
Python - append to dictionary by name with multilevels 1, 1.1, 1.1.1, 1.1.2 (hierarchical)
我使用 openpyxl 从 excel 文件中读取数据,最后提供一个 json 文件。问题是我无法找出一种算法来对 json(或 python 字典)进行分层组织。
数据形式如下:
输出应该是这样的:
{
'id' : '1',
'name' : 'first',
'value' : 10,
'children': [ {
'id' : '1.1',
'name' : 'ab',
'value': 25,
'children' : [
{
'id' : '1.1.1',
'name' : 'abc' ,
'value': 16,
'children' : []
}
]
},
{
'id' : '1.2',
...
]
}
这是我想出的,但我不能超越“1.1”,因为“1.1.1”和“1.1.1.1”等将与 1.1 处于同一级别。
from openpyxl import load_workbook
import re
from json import dumps
wb = load_workbook('resources.xlsx')
sheet = wb.get_sheet_by_name(wb.get_sheet_names()[0])
resources = {}
prev_dict = {}
list_rows = [ row for row in sheet.rows ]
for nrow in range(list_rows.__len__()):
id = str(list_rows[nrow][0].value)
val = {
'id' : id,
'name' : list_rows[nrow][1].value ,
'value' : list_rows[nrow][2].value ,
'children' : []
}
if id[:-2] == str(list_rows[nrow-1][0].value):
prev_dict['children'].append(val)
else:
resources[nrow] = val
prev_dict = resources[nrow]
print dumps(resources)
您需要通过 ID 访问您的数据,因此第一步是创建一个以 ID 为键的字典。为了便于数据操作,字符串 "1.2.3"
被转换为 ("1","2","3")
元组。 (列表不允许作为字典键)。这使得父密钥的计算非常容易 (key[:-1]
)。
有了这个准备,我们可以简单地填充每个项目父项的子列表。但在此之前,需要添加一个特殊的 ROOT 元素。它是顶级项目的父项。
就是这样。代码如下。
注意#1:它期望每个项目都有一个父项。这就是 1.2.2
被添加到测试数据中的原因。如果不是这种情况,请在注明的地方处理 KeyError
。
注意#2:结果是一个列表。
import json
testdata="""
1 first 20
1.1 ab 25
1.1.1 abc 16
1.2 cb 18
1.2.1 cbd 16
1.2.1.1 xyz 19
1.2.2 NEW -1
1.2.2.1 poz 40
1.2.2.2 pos 98
2 second 90
2.1 ezr 99
"""
datalist = [line.split() for line in testdata.split('\n') if line]
datadict = {tuple(item[0].split('.')): {
'id': item[0],
'name': item[1],
'value': item[2],
'children': []}
for item in datalist}
ROOT = ()
datadict[ROOT] = {'children': []}
for key, value in datadict.items():
if key != ROOT:
datadict[key[:-1]]['children'].append(value)
# KeyError = parent does not exist
result = datadict[ROOT]['children']
print(json.dumps(result, indent=4))
我使用 openpyxl 从 excel 文件中读取数据,最后提供一个 json 文件。问题是我无法找出一种算法来对 json(或 python 字典)进行分层组织。
数据形式如下:
输出应该是这样的:
{
'id' : '1',
'name' : 'first',
'value' : 10,
'children': [ {
'id' : '1.1',
'name' : 'ab',
'value': 25,
'children' : [
{
'id' : '1.1.1',
'name' : 'abc' ,
'value': 16,
'children' : []
}
]
},
{
'id' : '1.2',
...
]
}
这是我想出的,但我不能超越“1.1”,因为“1.1.1”和“1.1.1.1”等将与 1.1 处于同一级别。
from openpyxl import load_workbook
import re
from json import dumps
wb = load_workbook('resources.xlsx')
sheet = wb.get_sheet_by_name(wb.get_sheet_names()[0])
resources = {}
prev_dict = {}
list_rows = [ row for row in sheet.rows ]
for nrow in range(list_rows.__len__()):
id = str(list_rows[nrow][0].value)
val = {
'id' : id,
'name' : list_rows[nrow][1].value ,
'value' : list_rows[nrow][2].value ,
'children' : []
}
if id[:-2] == str(list_rows[nrow-1][0].value):
prev_dict['children'].append(val)
else:
resources[nrow] = val
prev_dict = resources[nrow]
print dumps(resources)
您需要通过 ID 访问您的数据,因此第一步是创建一个以 ID 为键的字典。为了便于数据操作,字符串 "1.2.3"
被转换为 ("1","2","3")
元组。 (列表不允许作为字典键)。这使得父密钥的计算非常容易 (key[:-1]
)。
有了这个准备,我们可以简单地填充每个项目父项的子列表。但在此之前,需要添加一个特殊的 ROOT 元素。它是顶级项目的父项。
就是这样。代码如下。
注意#1:它期望每个项目都有一个父项。这就是 1.2.2
被添加到测试数据中的原因。如果不是这种情况,请在注明的地方处理 KeyError
。
注意#2:结果是一个列表。
import json
testdata="""
1 first 20
1.1 ab 25
1.1.1 abc 16
1.2 cb 18
1.2.1 cbd 16
1.2.1.1 xyz 19
1.2.2 NEW -1
1.2.2.1 poz 40
1.2.2.2 pos 98
2 second 90
2.1 ezr 99
"""
datalist = [line.split() for line in testdata.split('\n') if line]
datadict = {tuple(item[0].split('.')): {
'id': item[0],
'name': item[1],
'value': item[2],
'children': []}
for item in datalist}
ROOT = ()
datadict[ROOT] = {'children': []}
for key, value in datadict.items():
if key != ROOT:
datadict[key[:-1]]['children'].append(value)
# KeyError = parent does not exist
result = datadict[ROOT]['children']
print(json.dumps(result, indent=4))