Hash from string

Hello,

I have a string like: ’ “gaz”=>“1”, “viz”=>“1”, “lift”=>“0”,
“kamra”=>“1”, “klima”=>“0” ’
Is it possible to convert this easily to hash without calling eval or
writing regexp?

eval is easy and unsecure. Regexp is not very simple if you want handle
every special case (nested values etc).

   Mage

On Aug 6, 2008, at 10:03 AM, Mage wrote:

 Mage

str = ’ “gaz”=>“1”, “viz”=>“1”, “lift”=>“0”, “kamra”=>“1”,
“klima”=>“0” ’

h = {}
str.split(’,’).each do |substr|
ary = substr.strip.split(’=>’)
h[ary.first.tr(’"’,’’)] = ary.last.tr(’"’,’’)
end

But that won’t handle nested values – that’s left for someone else
with more time than me.

Blessings,
TwP

Mage wrote:

Tim P. wrote:

with more time than me.
Won’t even work if any of the values contains a comma.

   Mage

Why don’t you use YAML?

{ :qwe => “asd”}.to_yaml
=> “— \n:qwe: asd\n”

YAML.load(({ :qwe => “asd”}.to_yaml))
=> {:qwe=>“asd”}

It works for most of things.

Tim P. wrote:

with more time than me.
Won’t even work if any of the values contains a comma.

   Mage

Maciej Tomaka wrote:

Why don’t you use YAML?

The input string isn’t generated by me, and I cannot change its format.

   Mage

On Wed, Aug 6, 2008 at 12:03 PM, Mage [email protected] wrote:

eval is easy and unsecure. Regexp is not very simple if you want handle
every special case (nested values etc).

You could try eval with a high SAFE level. Or write a quick parser
using TreeTop.


Avdi

Home: http://avdi.org
Developer Blog: Avdi Grimm, Code Cleric
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

Michael M. wrote:

map {|s|

It won’t work if any if the values has a comma, like str = ’ “gaz” =>
“1”, “lift” =>“white, small”’

split(/, +/) will break “white, small”

A much more complicated regexp should work. As far as I see I will stay
with eval.

   Mage

Mage wrote:

  Mage

You could do something like this:

#!/usr/bin/env ruby

UziMonkey [email protected]

str = %q{“gaz”=>“1”, “viz”=>“1”, “lift”=>“0”, “kamra”=>“1”,“klima”=>“0”}

hash = Hash[*
str.
split(/, +/).
map {|s|
s.match( /“([^”]+)“=>”([^“]+)”/ )[1,2]
}.
flatten
]

puts hash.inspect

But the regex makes a lot of assumptions. If the format of the hash
changes at all (for example, quotes removed or changed to single
quotes), it will break. If not, it should work fine.

Mage wrote:

Michael M. wrote:

map {|s|

It won’t work if any if the values has a comma, like str = ’ “gaz” =>
“1”, “lift” =>“white, small”’

split(/, +/) will break “white, small”

A much more complicated regexp should work. As far as I see I will stay
with eval.

   Mage

s = str.match(/^\s*{\s*(.+)}\s*$/).captures.first;
Hash[s.scan(/"([^"])"\s*=>\s*"([^"]*)"/).flatten]

Lets assume that each hash is in form:
{ “something” => “someting elswe”[, *] }

Escaped " in strings are not supported here.