Есть ли способ создать псевдоним/привязать массив в YAML?

Я использую Jammit для упаковки ресурсов для приложения Rails, и у меня есть несколько файлов ресурсов, которые я хотел бы включены в каждую из нескольких групп. Например, я хочу, чтобы Sammy и его подключаемые модули были в моих mobile и screen пакетах JS.

Я пробовал это:

sammy: &SAMMY
  - public/javascripts/vendor/sammy.js
  - public/javascripts/vendor/sammy*.js

mobile:
  <<: *SAMMY
  - public/javascripts/something_else.js

и это:

mobile:
  - *SAMMY

но оба помещают файлы Sammy JS во вложенный массив, который Jammit не может понять. Есть ли синтаксис для включения элементов массива непосредственно в другой массив?

NB: я понимаю, что в этом случае в массиве SAMMY всего два элемента, поэтому было бы неплохо дать каждому псевдоним и ссылаться на оба в каждом пакете. Это хорошо для данного случая, но быстро становится непригодным для сопровождения, когда есть пять или десять элементов с определенным порядком загрузки.


person James A. Rosen    schedule 09.02.2011    source источник
comment
Стандартные авторы отклонили эту функцию: github.com/yaml/yaml/issues/35.   -  person gavenkoa    schedule 04.12.2019


Ответы (5)


Ваш пример является допустимым YAML (удобным местом для проверки является YPaste), но не определено, что такое слияние делает. Согласно спецификации, ключ слияния может иметь значение:

  1. Сопоставление, и в этом случае оно объединяется с родительским сопоставлением.
  2. Последовательность сопоставлений, в этом случае каждое из них одно за другим объединяется с родительским сопоставлением.

Невозможно объединить последовательности на уровне YAML.

Однако вы можете сделать это в коде. Используя YAML из вашей второй идеи:

mobile:
  - *SAMMY

вы получите вложенные последовательности — так сгладьте их! Предполагая, что у вас есть отображение таких вложенных последовательностей:

data = YAML::load(File.open('test.yaml'))
data.each_pair { |key, value| value.flatten! }

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

person Jesse Beder    schedule 09.02.2011
comment
Вот пример: yaml.org/ypaste/803/index.html. Я только что проверил еще раз и заметил, что это не синтаксическая ошибка; дело в том, что эта конструкция не создает плоский массив; он создает карту, с которой Джаммит не может справиться. Я только что отредактировал вопрос, чтобы показать это. - person James A. Rosen; 09.02.2011
comment
@ Джеймс, извини, я не совсем понял, что ты объединяешь последовательности. Отредактировано. - person Jesse Beder; 09.02.2011
comment
Убедитесь, что вы сглаживаете (1) для мелкого сглаживания, чтобы не уничтожить свои массивы в значениях. - person Costi; 21.01.2015

Самое близкое решение, о котором я знаю, это:

sammy:
  - &SAMMY1
    public/javascripts/vendor/sammy.js
  - &SAMMY2
    public/javascripts/vendor/sammy*.js

mobile:
  - *SAMMY1
  - *SAMMY2
  - public/javascripts/something_else.js

В качестве альтернативы, как уже предлагалось, сгладьте вложенные списки во фрагменте кода.

Примечание. Согласно yaml-online-parser, ваше первое предложение не является допустимым использованием ‹ ‹ (используется для объединения ключей из двух словарей. Тогда якорь должен указывать на другой словарь, я полагаю.

person yngve    schedule 19.11.2014
comment
Это не сработает, если в sammy1/samm2 нужно несколько элементов. - person Andy Ray; 05.03.2020

Если вы хотите, чтобы mobile было равно sammy, вы можете просто сделать:

mobile: *SAMMY

Однако, если вы хотите, чтобы mobile содержал другие элементы в дополнение к элементам sammy, насколько мне известно, нет способа сделать это в YAML.

person sepp2k    schedule 09.02.2011

Это решение предназначено только для Symfony/PHP (соображения для других языков см. ниже)

Обратите внимание на ключи массива из справочной страницы массива PHP:

Строки, содержащие допустимые десятичные целые числа, если перед числом не стоит знак +, будут приведены к типу int. Например. ключ 8 будет фактически сохранен под 8. [...]

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

sammy: &SAMMY
  1: public/javascripts/vendor/sammy.js
  2: public/javascripts/vendor/sammy*.js

mobile:
  <<: *SAMMY
  3: public/javascripts/something_else.js

Вы даже можете перезаписать ключи и добавить новые:

laptop:
  <<: *SAMMY
  1: public/javascripts/sammy_laptop.js
  3: public/javascripts/something_else.js

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


Другие языки программирования

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

Например, в JS вы также можете получить доступ к числовым строковым ключам по их целочисленному значению:

const sammy = {"1": "public/javascripts/vendor/sammy.js"}

sammy["1"]; // "public/javascripts/vendor/sammy.js"
sammy[1]; // "public/javascripts/vendor/sammy.js"

Но вам нужно иметь в виду, что ваш первоначальный массив теперь является объектом, и что вам нужно будет перебирать его соответствующим образом, например:

Object.keys(sammy).forEach(key => console.log(sammy[key]))
person flu    schedule 26.04.2021

Как было предложено, когда вам нужно сгладить список, по крайней мере, в ruby, тривиально добавить спецификатор типа «!flatten» для мобильных устройств и реализовать класс, который расширяет Array, добавляет yaml_tag и сглаживает кодировщик seq на инициализация_с.

person Eric Woodruff    schedule 28.07.2016