XavM
XavM

Reputation: 873

Create Yaml without file

For some dark reasons, I have to convert a specific formated array to hash and a solution was to go through YAML.

I didn't reach to convert an array to hash through yaml without creating a file, could you help me ?

My Original Array could be like this one :

[
  ["lvl1"],
  [nil,"lvl2"],
  [nil, nil, "lvl3", "value1", "value2", "value3"],
  [nil, "lvl2bis"],
  [nil, nil, "lvl3bis", "value1bis", "value2bis", "value3bis"]
]

I transform this Array to string:

I got the following result:

lvl1:
  lvl2:
    lvl3: ["value1", "value2", "value3"]
  lvl2bis:
    lvl3bis: ["value1", "value2", "value3"]

If I save this text in a yml file and parse it like this:

hash = YAML.load(File.read(yml_file_path)) 

I got my hash:

{ "lvl1" => {
    "lvl2" => {
      "lvl3" => ["value1", "value2", "value3"]
    },
    "lvl2bis" => {
      "lvl3bis" => ["value1bis", "value2bis", "value3bis"]
    }
  }
}

If I do not save this text as yml file and try to load my yml_text, I obtain this :

yml_data = YAML.load(yml_text)
p yml_data
"lvl1 lvl2 lvl3,value1,value2,value3 lvl2bis lvl3bis,value1bis,value2bis,value3bis"

Is it impossible to go through YAML without creating a file ?

Upvotes: 0

Views: 165

Answers (2)

james2m
james2m

Reputation: 1580

This doesn't answer your YAML question as such, just converts the array directly into a hash:

def to_hash(array)
  default = ->(hash, key) { hash[key] = Hash.new(&default) }
  keys = []
  array.inject(Hash.new(&default)) do |hash, element|
    compacted = element.compact
    if compacted.length > 1
      nested_hash = keys.inject(hash) { |sub_hash, key| sub_hash[key] }
      nested_hash[compacted.shift] = compacted
    else
      keys = keys.take(element.count(nil))
      keys[keys.length] = compacted.shift
    end
    hash
  end
end

Upvotes: 1

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

YAML.load(
  inp.map(&:dup).map do |a| # #dup is required for safe #shift below
    count, arr = (0...a.size).each do |i|
      curr = a.shift
      break [i, curr] unless curr.nil?
    end
    "  " * count << arr << ": " << (a.empty? ? "" : a.inspect)
  end.join($/)
)
#⇒ {"lvl1"=>{"lvl2"=>{"lvl3"=>["value1", "value2", "value3"]},
#     "lvl2bis"=>{"lvl3bis"=>["value1bis", "value2bis", "value3bis"]}}}

Upvotes: 1

Related Questions