gpt4 book ai didi

python - 在python中将节点添加到json

转载 作者:太空宇宙 更新时间:2023-11-04 00:07:15 26 4
gpt4 key购买 nike

我正在尝试使用以下代码在 python 中生成自定义 JSON

root={}
Levels=[['L1','L1','L2'],
['L1','L1','L3'],
['L1','L2'],
['L2','L2','L3'],
['L2','L2','L1'],
['L3','L2'],
['L4','L2','L1'],
['L4','L2','L4']]

def append_path(root, paths):
if paths:
child = root.setdefault(paths[0], {})
append_path(child, paths[1:])

for p in Levels:
append_path(root, p)

def convert(d):
templist=[]
noofchildren=0
if(len(d.items())==0):
return ([{}],1)
for k,v in d.items():
temp,children=convert(v)
noofchildren+=children
if(temp):
templist.append({"name":k+"("+str(children)+")",'children':temp})
else:
templist.append({'name': k+"("+str(children)+")", 'children':[{}]})

return (templist,noofchildren)

# Print results
import json
print(json.dumps(convert(root)[0], indent=2))

输出是

[
{
"name": "L1(3)",
"children": [
{
"name": "L1(2)",
"children": [
{
"name": "L2(1)",
"children": [
{}
]
},
{
"name": "L3(1)",
"children": [
{}
]
}
]
},
{
"name": "L2(1)",
"children": [
{}
]
}
]
},
{
"name": "L2(2)",
"children": [
{
"name": "L2(2)",
"children": [
{
"name": "L3(1)",
"children": [
{}
]
},
{
"name": "L1(1)",
"children": [
{}
]
}
]
}
]
},
{
"name": "L3(1)",
"children": [
{
"name": "L2(1)",
"children": [
{}
]
}
]
},
{
"name": "L4(2)",
"children": [
{
"name": "L2(2)",
"children": [
{
"name": "L1(1)",
"children": [
{}
]
},
{
"name": "L4(1)",
"children": [
{}
]
}
]
}
]
}
]

我的数据集发生了一些变化

 Levels=[[['L1','L1','L2'],[10,20,30]],
[[['L1','L1','L3'],[10,15,20]],
[[['L1','L2'],[20,10]],
[[['L2','L2','L3'],[20,20,30]],
[[['L2','L2','L1'],[10,20,30]]
[[['L3','L2'],[10,20]]
[[['L4','L2','L1'],[10,20,10]]
[[['L4','L2','L4'],[20,40,50]]]

我想要的输出是水平的平均值以及计数

[
{
"name": "L1(3)#(13)", // taking avg of 10,10,20
"children": [
{
"name": "L1(2)#(17)", // taking avg of 20,15
"children": [
{
"name": "L2(1)#(30)",
"children": [
{}
]
},
{
"name": "L3(1)#(20)",
"children": [
{}
]
}
]
},
{
"name": "L2(1)#10",
"children": [
{}
]
}
]
},
{
"name": "L2(2)#(15)", // avg of 20,10
"children": [
{
"name": "L2(2)#(20)", // avg of 20,20
"children": [
{
"name": "L3(1)#(30)",
"children": [
{}
]
},
{
"name": "L1(1)#(30)",
"children": [
{}
]
}
]
}
]
},
{
"name": "L3(1)#(10)",
"children": [
{
"name": "L2(1)#(10)",
"children": [
{}
]
}
]
},
{
"name": "L4(2)#(15)",// avg of 10,20
"children": [
{
"name": "L2(2)#(30)", // avg of 20,40
"children": [
{
"name": "L1(1)# (10)",
"children": [
{}
]
},
{
"name": "L4(1)#(50)",
"children": [
{}
]
}
]
}
]
}
]

我如何更改我的代码以添加此信息?

最佳答案

前言

在进入解决方案之前,我想提一下以下几点:

  • 利用 Python 的面向对象编程功能!这使数据结构对您自己和 future 的读者来说都更加清晰。

  • 使用自定义类还可以让我们更轻松地存储元数据——即节点的实例数及其总值——同时构建中间树结构,而不是同时转换它。这也更有效,因为使用后一种方法,简单的朴素遍历算法会对节点进行重复访问!

  • 如果您希望输出(可靠地)保持路径插入的顺序,您应该使用 OrderedDict(来自 collections ) 而不是普通的 dict ({})。

  • 为没有子节点的节点输出一个空列表比一个空字典的列表更合乎逻辑:

    // Before
    "children": [
    {}
    ]

    // After
    "children": []

    原因是任何稍后将解析此数据的软件都可以安全地假设所有对象都有 "name""children" 字段,这是一个空字典没有。

  • Levels 数组中的列表边界和元素似乎格式不正确;你的意思是:

    Levels = [
    [['L1','L1','L2'],[10,20,30]],
    [['L1','L1','L3'],[10,15,20]],
    [['L1','L2'],[20,10]],
    [['L2','L2','L3'],[20,20,30]],
    [['L2','L2','L1'],[10,20,30]],
    [['L3','L2'],[10,20]],
    [['L4','L2','L1'],[10,20,10]],
    [['L4','L2','L4'],[20,40,50]],
    ]
  • 在数据主题上,由于节点和值遵循一对一映射(在每个路径内),使用元组列表会更合适而不是两个平行列表的列表:

    Levels = [
    [('L1', 10), ('L1', 20), ('L2', 30)],
    [('L1', 10), ('L1', 15), ('L3', 20)],
    [('L1', 20), ('L2', 10)],
    [('L2', 20), ('L2', 20), ('L3', 30)],
    [('L2', 10), ('L2', 20), ('L1', 30)],
    [('L3', 10), ('L2', 20)],
    [('L4', 10), ('L2', 20), ('L1', 10)],
    [('L4', 20), ('L2', 40), ('L4', 50)]
    ]
  • 您的预期输出似乎有误:

    {
    "name": "L3(1)#(10)",
    "children": [
    {
    "name": "L2(1)#(10)", <--- this should be #(20)
    "children": [
    {}
    ]
    }
    ]
    },

实现

  • 对于您当前的数据格式(列表对):

    # A dictionary here corresponds to an array of nodes in JSON
    # the "name" fields serve as the keys and "children" as the values
    class data_node(OrderedDict):
    def __init__(self, **kwargs):
    super(data_node, self).__init__(**kwargs)
    self.instances = 0
    self.total = 0

    def insert(self, names, values):
    # Python lists are truthy, so no need for len(path) == 0
    if not (names or values):
    return

    # create the child node if it doesn't exist
    child = self.get(names[0], data_node())

    # add the value to the total
    # and increment the instance counter
    child.instances += 1
    child.total += values[0]

    # recursive call on the child
    # with the rest of the path
    child.insert(names[1:], values[1:])
    self[names[0]] = child

    def convert(self):
    return [
    {
    "name": "{}({})#({})".format(
    name,
    child.instances,
    child.total / child.instances # mean
    ),
    "children": child.convert()
    }
    for name, child in self.items()
    ]

    tree = data_node()
    for path in Levels:
    tree.insert(path[0], path[1])
    print json.dumps(tree.convert(), indent=2)
  • 对于我建议的数据格式(元组列表):

    # only the insertion method differs
    # all other parts of the class are unchanged
    def insert(self, path):
    if not path:
    return
    name, value = path[0]
    child = self.get(name, data_node())
    child.instances += 1
    child.total += value
    child.insert(path[1:])
    self[name] = child

    ...

    for path in Levels:
    tree.insert(path) # simpler function signature

编辑:

如果出于某种原因您希望叶节点格式为 [{}] 而不是 [],则只需要进行简单的更改:

# in convert()
{
"name": ..., # as before

# again exploiting the truthy-ness property of arrays
"children": child.convert() or [{}]
}

输出

根据我在前言中的评论,这两种实现都提供了正确的 JSON 输出:

[
{
"name": "L1(3)#(13)",
"children": [
{
"name": "L1(2)#(17)",
"children": [
{
"name": "L2(1)#(30)",
"children": []
},
{
"name": "L3(1)#(20)",
"children": []
}
]
},
{
"name": "L2(1)#(10)",
"children": []
}
]
},
{
"name": "L2(2)#(15)",
"children": [
{
"name": "L2(2)#(20)",
"children": [
{
"name": "L3(1)#(30)",
"children": []
},
{
"name": "L1(1)#(30)",
"children": []
}
]
}
]
},
{
"name": "L3(1)#(10)",
"children": [
{
"name": "L2(1)#(20)",
"children": []
}
]
},
{
"name": "L4(2)#(15)",
"children": [
{
"name": "L2(2)#(30)",
"children": [
{
"name": "L1(1)#(10)",
"children": []
},
{
"name": "L4(1)#(50)",
"children": []
}
]
}
]
}
]

关于python - 在python中将节点添加到json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53698221/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com