Reputation: 2441
I have a string "Animals ( Reptiles Birds ( Eagles Pigeons Crows ) )"
and I need to return:
a = [
{
"Animals" => [
{
"Reptiles" => nil
},
{
"Birds" => [
{ "Eagles" => nil },
{ "Pigeons" => nil },
{ "Crows" => nil }
]
}
]
}
]
I don't understand how I can do it. Where I can find some example or what I can search in google?
Upvotes: 4
Views: 294
Reputation: 110725
Here is a one way you could convert the string to an array.
Code
def arrayify(arr)
a = split_arr(arr)
a.map do |h|
k = h.keys.first
v = h.values.first
case v
when Array then { k => arrayify(v) }
else { k=>v }
end
end
end
def split_arr(arr)
a = []
while arr.any?
word = arr.shift
if arr.empty? || arr.first != ?(
a << { word=>nil }
else
arr.shift
close_count = 0
b = []
loop do
token = arr.shift
case token
when ?)
break if close_count == 0
close_count -= 1
when ?( then close_count += 1
end
b << token
end
a << { word=>b }
end
end
a
end
Example
str = "Animals ( Reptiles Birds ( Eagles Pigeons Crows ) ) Foods ( " +
"Snacks Breakfast ( Pancakes Waffles ) )"
arrayify(str.split)
#=> [{"Animals"=>[{"Reptiles" =>nil},
# {"Birds" =>[{"Eagles" =>nil},
# {"Pigeons"=>nil},
# {"Crows" =>nil}
# ]
# }
# ]
# },
# {"Foods" =>[{"Snacks" =>nil},
# {"Breakfast"=>[{"Pancakes"=>nil},
# {"Waffles" =>nil}
# ]
# }
# ]
# }
# ]
Upvotes: 1
Reputation: 110725
This works with your example, but I don't know how general it is.
Code
def arrayify(str)
eval('['+str.gsub(/(\w+)\s+\(/,'{\1=>[')
.gsub( /(?!\{)(\w+)\s+/, '{\1=>nil},')
.gsub(')', ']}')
.gsub(/\b(\w+)\b/,"\"\\1\"")+']')
end
Example
str = "Animals ( Reptiles Birds ( Eagles Pigeons Crows ) )"
arrayify(str)
#=> [{ "Animals"=>[{ "Reptiles"=>"nil"},
# { "Birds" =>[{ "Eagles" =>"nil" },
# { "Pigeons"=>"nil" },
# { "Crows" =>"nil" }
# ]
# }
# ]
# }
# ]
Explanation
s1 = str.gsub(/(\w+)\s+\(/,'{\1=>[')
#=> "{Animals=>[ Reptiles {Birds=>[ Eagles Pigeons Crows ) )"
s2 = s1.gsub( /(?!\{)(\w+)\s+/, '{\1=>nil},')
#=> "{Animals=>[ {Reptiles=>nil},{Birds=>[ {Eagles=>nil},{Pigeons=>nil},{Crows=>nil},) )"
s3 = s2.gsub(')', ']}')
#=> "{Animals=>[ {Reptiles=>nil},{Birds=>[ {Eagles=>nil},{Pigeons=>nil},{Crows=>nil},]} ]}"
s4 = s3.gsub(/\b(\w+)\b/,"\"\\1\"")
#=> "{\"Animals\"=>[ {\"Reptiles\"=>\"nil\"},{\"Birds\"=>[ {\"Eagles\"=>\"nil\"},{\"Pigeons\"=>\"nil\"},{\"Crows\"=>\"nil\"},]} ]}"
eval('['+s4+']')
#=> <result in example>
Pardon me, but I have to run. The eval
police are coming.
Upvotes: 1
Reputation: 78553
I don't understand how I can do it. Where I can find some example or what I can search in google?
Using a recursive regex is one option, especially if the parenthesis are properly balanced:
http://www.regular-expressions.info/recurse.html
If it's over your head, recursively plough through the string using a normal regex. Match something like:
[a-z]+ ?([^()]*)
... then replace the match with a place holder in the original string. Rinse, repeat.
Using a parser is an alternative option. You could write a simplistic one, or use a tool e.g.:
http://thingsaaronmade.com/blog/a-quick-intro-to-writing-a-parser-using-treetop.html
Upvotes: 1