我正在尝试在YAML中做我认为简单的事情。这是一个具有重复元素的简单层次结构。下面的第一个例子非常接近,但每个节点序列元素都会触发错误:;序列条目的错误缩进";。我看不出它出了什么问题。
注意,我在下面包含了一个有效的示例,但它使用了唯一的键,这不是我想要的。
- agegrp: 1
- node : "(14, 6)"
# id: "(14, 6)"
- branch : "to 7"
id : "to 7"
tocond : 7
pr : 1.0
next : (0, 0)
- node : "(14, 7)"
# id: "(14,7)"
- branch : "to 7"
id : "to 7"
tocond : 7
pr : 0.85
next : (0, 0)
- branch : "to 8"
id : "to 8"
tocond : 8
pr : 0.15
next : (4, 4)
- agegrp : 2
- node : "(14, 6)"
# id: "(14, 6)"
- branch : "to 7"
id : "to 7"
tocond : 7
pr : 1.0
next : (0, 0)
- node : "(14, 7)"
# id: "(14,7)"
- branch : "to 7"
id : "to 7"
tocond : 7
pr : 0.85
next : (0, 0)
- branch : "to 8"
id : "to 8"
tocond : 8
pr : 0.15
next : (4, 4)
请注意,以下操作有效,但我不希望分支和节点具有唯一的名称。我想要一个重复的结构。我可以在分支和节点前面使用破折号,但这会导致另一个问题:序列条目的缩进不正确。
agegrp:
id: 1
node (14, 6):
# id: "(14, 6)"
branch:
id: "to 7"
tocond: 7
pr: 1.0
next: (0, 0)
node (14,7):
# id: "(14,7)"
branch to 7:
id: "to 7"
tocond: 7
pr: 0.85
next: (0, 0)
branch to 8:
id: "to 8"
tocond: 8
pr: 0.15
next: (4, 4)
将有5个年龄组。节点在年龄组中。分支位于节点内。每个分支有3个属性。我可以在每个节点下使用一个id项,而不是像上面显示的那样。
我对什么时候必须使用前导破折号和什么时候不使用感到困惑。我很困惑什么时候允许一个值,什么时候不允许。
这在YAML中可能吗?TOML不喜欢等级制度。到目前为止,我把它放在csv中,解析它,并用代码构建一个字典。我想我可以使用一种本机表示层次结构的格式。
我想要的输出:
- 年龄的数组或字典。永远不会超过10个,数组也可以
- 对于每个年龄组,节点的dict
- 对于每个节点,分支的数组或dict
这里有一个例子:这里有一条针对年龄组的格言:
(1, 1) =>
CovidSim.Branch(5, 5, 0.2, (2, 1), "nil", "nil")
CovidSim.Branch(5, 6, 0.65, (2, 2), "nil", "mild")
CovidSim.Branch(5, 7, 0.15, (2, 3), "nil", "sick")
(2, 1) =>
CovidSim.Branch(5, 3, 0.8, (0, 0), "nil", "recovered")
CovidSim.Branch(5, 7, 0.2, (3, 3), "nil", "sick")
(2, 2) =>
CovidSim.Branch(6, 6, 1.0, (3, 2), "mild", "mild")
(2, 3) =>
CovidSim.Branch(7, 7, 0.85, (3, 3), "sick", "sick")
CovidSim.Branch(7, 8, 0.15, (3, 4), "sick", "severe")
(3, 2) =>
CovidSim.Branch(6, 3, 1.0, (0, 0), "mild", "recovered")
(3, 3) =>
CovidSim.Branch(7, 3, 0.8, (0, 0), "sick", "recovered")
CovidSim.Branch(7, 7, 0.1, (5, 3), "sick", "sick")
CovidSim.Branch(7, 8, 0.1, (4, 4), "sick", "severe")
(3, 4) =>
CovidSim.Branch(8, 3, 0.45, (0, 0), "severe", "recovered")
CovidSim.Branch(8, 8, 0.5, (4, 4), "severe", "severe")
CovidSim.Branch(8, 4, 0.05, (0, 5), "severe", "dead")
(4, 4) =>
CovidSim.Branch(8, 3, 0.85, (0, 0), "severe", "recovered")
CovidSim.Branch(8, 8, 0.1, (5, 4), "severe", "severe")
CovidSim.Branch(8, 4, 0.05, (0, 5), "severe", "dead")
(5, 3) =>
CovidSim.Branch(7, 3, 0.9, (0, 0), "sick", "recovered")
CovidSim.Branch(7, 4, 0.1, (0, 5), "sick", "dead")
(5, 4) =>
CovidSim.Branch(8, 3, 0.6, (0, 0), "severe", "recovered")
CovidSim.Branch(8, 4, 0.4, (0, 5), "severe", "dead")
外部容器是一个由5个年龄组dict组成的数组。
(注意,这个例子在我减少的每个分支中都包含一些额外的字段。)
谢谢!
如果您查看集合的YAML规范
YAML的块集合对范围使用缩进,并从每个范围开始进入自己的行。
块序列用破折号表示每个条目和空格("-")。
映射使用冒号和空格(":")来标记每个key:值对。
注释以octhorpe开头(也称为"hash"、"sharp"、"pound"或"数字符号"-"#")。
所以你的
- agegrp: 1
是序列和地图的融合
你可以做一些类似的事情
---
-
id: 1
nodes:
-
branches:
-
id: "to 7"
next: "(0, 0)"
pr: 1.0
tocond: 7
-
id: "to 7"
next: "(0, 0)"
pr: 0.85
tocond: 7
-
id: "to 8"
next: "(4, 4)"
pr: 0.15
tocond: 8
id: "(14, 6)"
如果这符合您的需求
根据您自己的答案:YAML允许您将实体的名称放入YAML文件中。它通过为标签提供语法来做到这一点。下面是一个文件的外观示例:
!agegrp 4:
!node [9,6]:
- !branch
tocond: 6
next:
- 14
- 6
pr: 1.0
!node [9,5]:
- !branch
tocond: 3
next:
- 0
- 0
pr: 0.8
- !branch
tocond: 7
next:
- 14
- 7
pr: 0.2
注意,我使用YAML序列作为节点坐标,因为看起来您无论如何都想将它们解析为数字对((9,6)
将被解析为字符串)。你可以保留原来的语法。
这样做的目的是将标签后面的值直接与其关联。因此,4
将被标记为!agegrp
,序列[9,6]
将被标记成!node
,包含tocond
等的映射将被标记到!branch
。像这样的本地标签是应用程序定义的;您将需要在大多数YAML实现中为它们注册处理程序。
从语义上讲,这将把4
标记为agegrp(不管是什么),而节点不是agegrpobject的一部分——使用此标记,只有密钥4
被标记为agegrp。当然,你如何处理这个文件取决于你自己。另一种选择是:
4: !agegrp
!node [9,6]:
…
现在,包含节点的映射标记为agegrp,4
只是映射中的一个键(可能解析为整数)。
如果你想让ID成为对象的一部分,你可以将文档转换为基于序列的结构,@KeepCalmAndCarryOn已经展示了实现这一点的常用方法,下面是一个使用标签的方法:
- !agegrp
- !id 4
- !node
- !id [9,6]
- !branch
tocond: 6
next:
- 14
- 6
pr: 1.0
- !node
- !id [9,5]
- !branch
tocond: 3
next:
- 0
- 0
pr: 0.8
- !branch
tocond: 7
next:
- 14
- 7
pr: 0.2
这样做的目的是使节点的内部结构变平,以便ID和分支可以在同一级别上。这需要加载代码在加载该YAML时正确区分!id
和!branch
节点。这种结构通常用于XML中,XML不像YAML那样提供映射,因此,所有嵌套结构都是序列,不同的子级通过其元素名称来区分。
感谢您的帮助。我并没有想到YAML和创建没有任何名称的实体组@KeepCalmAndCarryOn:您的结构生成了一个节点数组,其中一个id项和一个分支项位于同一级别(分支项是分支的数组,每个分支都是属性的dict。这很有效,但显示得不太好,而且更难处理(但肯定包含了我示例中的所有信息)。
我更喜欢严格的等级制度。我手工编码了json。然后,将json解析为嵌套的julia对象:一个dicts数组,如下所示:
Dict{String,Any} with 5 entries:
"4" => Dict{String,Any}("(9,6)"=>Any[Dict{String,Any}("tocond"=>6,"next"=>Any…
"1" => Dict{String,Any}("(9,6)"=>Any[Dict{String,Any}("tocond"=>6,"next"=>Any…
"5" => Dict{String,Any}("(9,6)"=>Any[Dict{String,Any}("tocond"=>6,"next"=>Any…
"2" => Dict{String,Any}("(9,6)"=>Any[Dict{String,Any}("tocond"=>6,"next"=>Any…
"3" => Dict{String,Any}("(9,6)"=>Any[Dict{String,Any}("tocond"=>6,"next"=>Any…
输出被截断,但您可以将每个年龄组视为一个键,并将节点的dict作为其值。每个节点dict显示第一个键(一个节点),其值为一个分支数组。分支数组中的每个项都是分支的每个属性的字段的dict。
一个agegrp看起来像这样:
Dict{String,Any} with 8 entries:
"(9,6)" => Any[Dict{String,Any}("tocond"=>6,"next"=>Any[14, 6],"pr"=>1.0)]
"(9,5)" => Any[Dict{String,Any}("tocond"=>3,"next"=>Any[0, 0],"pr"=>0.8), Di…
"(14,6)" => Any[Dict{String,Any}("tocond"=>3,"next"=>Any[0, 0],"pr"=>1.0)]
"(9,7)" => Any[Dict{String,Any}("tocond"=>7,"next"=>Any[14, 7],"pr"=>0.85), …
"(5,5)" => Any[Dict{String,Any}("tocond"=>5,"next"=>Any[9, 5],"pr"=>0.2), Di…
"(14,8)" => Any[Dict{String,Any}("tocond"=>3,"next"=>Any[0, 0],"pr"=>0.45), D…
"(14,7)" => Any[Dict{String,Any}("tocond"=>3,"next"=>Any[0, 0],"pr"=>0.85), D…
"(19,8)" => Any[Dict{String,Any}("tocond"=>3,"next"=>Any[0, 0],"pr"=>0.9), Di…
然后,我取了这个Julia嵌套对象(有点粗糙,但结构更清晰——至少对我来说是这样),并将其通过YAML来创建有效的YAML输出。
这个YAML正是我真正想要的,即使对于正确使用YAML的人来说它看起来很恶心。这里只有一个agegrp(其他的结构相同,在YAML文档中按顺序排列):
4: # the id of an agegrp
(9,6): # the id of a node
- tocond: 6 # first property of a branch
next:
- 14
- 6
pr: 1.0
(9,5):
- tocond: 3
next:
- 0
- 0
pr: 0.8
- tocond: 7
next:
- 14
- 7
pr: 0.2
(14,6):
- tocond: 3
next:
- 0
- 0
pr: 1.0
(9,7):
- tocond: 7
next:
- 14
- 7
pr: 0.85
- tocond: 8
next:
- 14
- 8
pr: 0.15
<rest of output truncated...>
这遵循了我想要的层次结构:
top: an agegroup id
then a node (with more following after the indented children)
then a branch
then an array of the branches properties
我把实体的名称(agegrp、node、branch)与每个实体的特定实例的实际值混合在一起,真的把自己搞砸了——就像我试图用它的类型来标记每件事一样。在Dict中你不会这么做。我在这里使用Julia,但Dict本质上与Python中的相同。
因此,对YAML的尝试有点令人沮丧。但是,它将比我开始使用的CSV更容易输入,也比手工编写JSON更容易。所以,一次成功的尝试!