Reputation: 873
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:
For a string
yml_text = []
array.each do |line|
yml_line = line.join(",").gsub(/\G,/, ' ').sub(/,+\z/, ']').sub(/:,+/, ': [')
yml_text << yml_line
end
yml_text = yml_text.join("\n")
For a file
f = File.open(yml_file_path, "w")
array.each do |line|
yml_line = line.join(",").gsub(/\G,/, ' ').sub(/,+\z/, ']').sub(/:,+/, ': [')
f.puts(yml_line)
end
f.close
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
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
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