Нумерованный список в виде массива YAML

Вместо

key:
    - thisvalue
    - thatvalue
    - anothervalue

Я бы хотел

key:
    1. thisvalue
    2. thatvalue
    3. anothervalue

чисто для удобочитаемости, с той же интерпретацией {key: [thisvalue, thatvalue, anothervalue]}.

Похоже, это не является частью базового синтаксиса YAML, но есть ли способ добиться этого — возможно, используя некоторые из продвинутая магия возможна в YAML?

(Я понимаю, что это можно аппроксимировать, написав список как:

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

но это уродливый хак, и я бы предпочел решение, в котором числа имели семантическую цель, а не были просто частью текста значения, которое также требует анализа и удаления.)


person sundar - Remember Monica    schedule 02.08.2015    source источник
comment
Пожалуйста, смотрите обновление моего поста (ВАЖНЫЙ раздел в конце).   -  person rbaleksandar    schedule 03.08.2015


Ответы (2)


В 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, вам нужно отсортировать словарь, который у вас есть как псевдосписок, по ключу, а затем извлечь значения и добавить их в свой окончательный список.

person rbaleksandar    schedule 02.08.2015
comment
Это блестяще! Спасибо. Я собирался добавить к вопросу, что точное форматирование чисел для меня не имеет значения, но я мысленно не связывал это с превращением чисел в ключи на карте. Ruby, кажется, читает хэши в порядке, и уже был выбранным языком для анализа этого, но даже в других языках числовая сортировка ключей позаботится об упорядочении, так что это вполне осуществимое решение для моего варианта использования. - person sundar - Remember Monica; 02.08.2015
comment
Круто, рад, что это помогло. :) - person rbaleksandar; 02.08.2015
comment
@sundar кстати, я почти уверен, что это неэффективно во время процесса синтаксического анализа, особенно для больших списков, поскольку вы в основном создаете отдельный словарь для каждой записи, а не просто добавляете элемент в список. Имейте это в виду, если хотите работать с огромными наборами данных. - person rbaleksandar; 02.08.2015

При использовании Python, чтобы иметь возможность сохранить порядок ключей в сопоставлениях YAML (и комментариях, именах якорей и т. д.), сопоставления считываются в специальные производные orderdict, если вы используете 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 они, конечно, упорядочены. Если синтаксический анализатор не выбрасывает эту информацию, вещи намного полезнее, например. для сравнения ревизий файла.

person Anthon    schedule 03.08.2015
comment
Простите, а чем ваш ответ отличается от моего? XD За исключением того, что вы используете нестандартную пользовательскую библиотеку, что делает код не совсем переносимым. - person rbaleksandar; 05.08.2015
comment
По состоянию на лето 2015 года в стандартной библиотеке Python нет ничего для чтения файлов YAML, поэтому вы можете использовать только нестандартную, пользовательскую библиотеку (ruamel.yaml. PyYaml на основе syck, libyaml). Я обновил ответ, чтобы отдать вам должное за использование сопоставлений YAML. Обратите внимание, что я не полагаюсь на некоторые после факта повторного заказа ключей, как это делает ваше предложение, сопоставления остаются упорядоченными в оба конца, а также работают, если у вас есть ключи вида 1, 1a, ...9, 10, 10a, а также любой (случайный набор) ключей, которые должны сохранять порядок YAML-файла, - person Anthon; 05.08.2015
comment
Я забыл, что PyYaml и libyaml не входят в стандартные модули. фейспалм - person rbaleksandar; 06.08.2015
comment
@rbaleksandar Нет проблем, на самом деле очень жаль, ИМО, что нет стандартного модуля yaml. Но PyYAML в настоящее время даже не совместим с последней спецификацией в некоторых областях, что делает его в настоящее время даже не хорошим кандидатом. - person Anthon; 06.08.2015
comment
:-/ И все это с учетом того, как много YAML используется вместе с Python. Я работаю с OpenCV, ROS и т. д., и все они сильно зависят от разбора файлов YAML. Хм, действительно жаль. - person rbaleksandar; 06.08.2015