使用YAML数组作为编号列表

5

取代

key:
    - thisvalue
    - thatvalue
    - anothervalue

我想要

key:
    1. thisvalue
    2. thatvalue
    3. anothervalue

仅为了人类可读性,与{key: [thisvalue, thatvalue, anothervalue]}的相同解释。

这似乎不是基本的YAML语法的一部分,但是否有一种方法可以实现这一点 - 也许使用YAML中可能存在的一些高级技巧

(我意识到可以将列表写成以下形式来近似:

key:
    - 1. thisvalue
    - 2. thatvalue
    - 3. anothervalue

但这是一个丑陋的 hack,我更喜欢一个数字具有语义目的的解决方案,而不仅仅是值文本的一部分,这也需要被解析和删除。

请查看我帖子的更新(末尾的重要部分)。 - rbaleksandar
2个回答

4
在YAML中无法做到这一点。但是,您可以使用普通的元素嵌套,然后在解析期间基于这些生成数组/列表/字典:
my_numbered_pseudo_list:
  1: a
  2: b
  3: c
  ...
  n: x

当你加载上面的示例时,你会得到一个键为“my_numbered_pseudo_list”的字典,它的值是包含所有嵌套对的字典{"1" : "a", "2" : "b", ..., "n" : "x"}。这里是一个示例,看起来像这样:
import yaml

doc = '''
list:
  1: a
  2: b
  3: c
  4: d
'''

y = yaml.load(doc);
list = []

for i in y['list']:
    list.append(y['list'].get(i))

print list

这将给你

['a', 'b', 'c', 'd']

如果您想确保订单实际上被保存在YAML文件中,您需要进行排序,以获取一个有序的最终列表,其中保留了YAML文件中描述的顺序。
我还看到过有人在结果字典(这里是“列表”)上使用有序哈希调用(例如Ruby,我不熟悉),因此您可能需要深入挖掘一下。
重要提示!
阅读这里这里。简而言之,为了确保从您的YAML获得真正有序的列表,您必须按键对字典进行排序,然后提取值并将其附加到最终列表中。

太棒了!谢谢。我本来要补充一下,对数字的精确格式并不重要,但是我没有意识到可以将这些数字转换成地图中的键。 Ruby似乎可以按顺序读取哈希表,并且已经是解析此问题的首选语言,但即使在其他语言中,对键进行数值排序也可以解决排序问题,因此这对于我的使用情况来说是个相当可行的解决方案。 - Sundar R
很酷,很高兴能帮到你。 :) - rbaleksandar
@sundar 顺便说一下,我相当确定在解析过程中这样做是低效的,特别是对于大型列表来说,因为你基本上是为每个条目创建一个单独的字典,而不是将项目追加到列表中。如果你想处理大数据集,请记住这一点。 - rbaleksandar

2
在使用Python时,为了能够保留YAML映射中的键顺序(以及注释、锚点名称等),如果使用ruamel.yaml(免责声明:我是作者),则映射将被读入特殊的有序字典派生类中,并且使用RoundTripLoader。
这些函数可以透明地作为字典来使用,但是采用rbaleksandar在其答案中提出的语法,您只需执行以下操作即可:
import ruamel.yaml as yaml

yaml_str = """\
key:
    1: thisvalue
    2: thatvalue
    3: anothervalue
    4: abc
    5: def
    6: ghi
"""

data = yaml.load(yaml_str, Loader=yaml.RoundTripLoader)
y = data['key']
print y.keys()[2:5]
print y.values()[2:5]
print y.items()[2:5]

获得:
[3, 4, 5]
['anothervalue', 'abc', 'def']
[(3, 'anothervalue'), (4, 'abc'), (5, 'def')]

在加载数据后不需要任何特殊的努力。

YAML规范说明键的顺序不能保证,但在YAML文件中它们当然是有序的。如果解析器不丢弃这些信息,那么对于比较文件修订版本之间的差异等方面会更加有用。


请原谅,您的答案与我的有何不同?XD 除了您使用了非标准自定义库,这使得代码不太可移植。 - rbaleksandar
截至2015年夏季,标准Python库中没有用于读取YAML文件的内容,因此非标准的自定义库是您唯一可以使用的东西(ruamel.yaml. PyYaml基于syck、libyaml)。我已更新答案,以便为您使用YAML映射而给予信用。请注意,我不依赖某些事后重新排序键的方法,映射在往返时保持有序,并且如果您具有形式为11a、... 91010a的键以及必须保持YAML文件顺序的任何(随机集合)键,则也适用。 - Anthon
我忘记了PyYaml和libyaml不是标准模块的一部分。扇自己一个耳光 - rbaleksandar
@rbaleksandar 没问题,实际上我认为很遗憾没有标准的yaml模块。但是PyYAML目前在某些方面甚至不兼容最新规范,因此它目前甚至不是一个好的选择。 - Anthon
考虑到YAML与Python一起使用的频率有多高,这一切都让人感到烦恼。我使用OpenCV、ROS等工具,它们都严重依赖解析YAML文件。哼,真是遗憾。 - rbaleksandar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接