Сохранить порядок ключей при загрузке YAML из файла в Ruby

Я хочу сохранить порядок ключей в файле YAML, загруженном с диска, каким-то образом обработанном и записанном обратно на диск.

Вот базовый пример загрузки YAML в Ruby (v1.8.7):

require 'yaml'

configuration = nil
File.open('configuration.yaml', 'r') do |file|
  configuration = YAML::load(file)
  # at this point configuration is a hash with keys in an undefined order
end

# process configuration in some way

File.open('output.yaml', 'w+') do |file|
  YAML::dump(configuration, file)
end

К сожалению, это нарушит порядок ключей в configuration.yaml после построения хеша. Я не могу найти способ контролировать, какая структура данных используется YAML::load(), например. Алиба orderedmap.

Мне не повезло искать в Интернете решение.


person hiwaylon    schedule 10.05.2011    source источник
comment
Какую версию рубина вы используете?   -  person sawa    schedule 11.05.2011
comment
Тогда у вас нет возможности сделать это. Хеши в ruby ​​1.8 не имеют концепции упорядочения.   -  person sawa    schedule 11.05.2011
comment
@sawa: Разве в Ruby 1.8 нет драгоценного камня, который делает упорядоченные хэши? (Я не могу вспомнить, исправляет ли он Hash или создает свой собственный класс)   -  person Andrew Grimm    schedule 12.05.2011
comment
@Эндрю Я нашел OrderedHash: rubygems.org/gems/orderedhash. Похоже, он создает подкласс Hash, содержащий информацию о заказе в виде массива переменных экземпляра.   -  person sawa    schedule 12.05.2011


Ответы (3)


Если вы по какой-либо причине застряли на 1.8.7 (как и я), я прибегаю к использованию active_support/ordered_hash. Я знаю, что activesupport кажется большим включением, но они переработали его в более поздних версиях, так что вам в значительной степени требуется только та часть, которая вам нужна в файле, а остальное опускается. Просто gem install activesupport и включите его, как показано ниже. Кроме того, в вашем файле YAML обязательно используйте объявление !!omap (и массив хэшей). Пример времени!

# config.yml #

months: !!omap
  - january: enero
  - february: febrero
  - march: marzo
  - april: abril
  - may: mayo

Вот как выглядит Рубин за ним.

# loader.rb #

require 'yaml'
require 'active_support/ordered_hash'

# Load up the file into a Hash
config = File.open('config.yml','r') { |f| YAML::load f }

# So long as you specified an !!omap, this is actually a
# YAML::PrivateClass, an array of Hashes
puts config['months'].class

# Parse through its value attribute, stick results in an OrderedHash,
# and reassign it to our hash
ordered = ActiveSupport::OrderedHash.new
config['months'].value.each { |m| ordered[m.keys.first] = m.values.first }
config['months'] = ordered

Я ищу решение, которое позволит мне рекурсивно копаться в Hash, загруженном из файла .yml, искать эти объекты YAML::PrivateClass и преобразовывать их в ActiveSupport::OrderedHash. Я могу опубликовать вопрос по этому поводу.

person Ben Kreeger    schedule 11.10.2011

Используйте Руби 1.9.x. Предыдущая версия Ruby не сохраняет порядок хэш-ключей, но 1.9 сохраняет.

person ravinggenius    schedule 11.05.2011
comment
В то время я застрял с 1.8.7. - person hiwaylon; 26.01.2013

Кто-то придумал такую ​​же проблему. Существует гем упорядоченный хэш. Обратите внимание, что это не хэш, он создает подкласс хеша. Вы можете попробовать, но если вы обнаружите проблему с YAML, вам следует подумать об обновлении до ruby ​​1.9.

person sawa    schedule 12.05.2011