fetch the Hash from a string

24 views
Skip to first unread message

Love U Ruby

unread,
Aug 26, 2013, 3:42:01 PM8/26/13
to rubyonra...@googlegroups.com
require 'json'

str = "1=2,3=(4=5,6=7)"
new_str = str.gsub(/=|\(|\)/) do |m|
if m == "="
m= "=>"
elsif m == "("
m = "{"
else
m = "}"
end
end

new_str = new_str.prepend("{") << "}"
# => "{1=>2,3=>{4=>5,6=>7}}"

JSON.parse(new_str)
# ~>
/home/kirti/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/json/common.rb:155:in
`parse': 757: unexpected token at '{1=>2,3=>{4=>5,6=>7}}'
(JSON::ParserError)
# ~> from
/home/kirti/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/json/common.rb:155:in
`parse'
# ~> from -:15:in `<main>'


My question is how should I get the hash {1=>2,3=>{4=>5,6=>7}} from that
string?

--
Posted via http://www.ruby-forum.com/.

Hassan Schroeder

unread,
Aug 26, 2013, 3:58:11 PM8/26/13
to rubyonrails-talk
On Mon, Aug 26, 2013 at 12:42 PM, Love U Ruby <li...@ruby-forum.com> wrote:
>
> My question is how should I get the hash {1=>2,3=>{4=>5,6=>7}} from that
> string?

Why don't you generate valid JSON in the first place?

`{1=>2,3=>{4=>5,6=>7}}.to_json` would show you what the string
should look like (and why your example is so broken).

--
Hassan Schroeder ------------------------ hassan.s...@gmail.com
http://about.me/hassanschroeder
twitter: @hassan

Love U Ruby

unread,
Aug 26, 2013, 4:07:57 PM8/26/13
to rubyonra...@googlegroups.com
Hassan Schroeder wrote in post #1119612:
> On Mon, Aug 26, 2013 at 12:42 PM, Love U Ruby <li...@ruby-forum.com>
> wrote:
>>
>> My question is how should I get the hash {1=>2,3=>{4=>5,6=>7}} from that
>> string?
>
> Why don't you generate valid JSON in the first place?
>
> `{1=>2,3=>{4=>5,6=>7}}.to_json` would show you what the string
> should look like (and why your example is so broken).

Humm.. its working now..

require 'json'

JSON.parse({1=>2,3=>{4=>5,6=>7}}.to_json)
# => {"1"=>2, "3"=>{"4"=>5, "6"=>7}}

Love U Ruby

unread,
Aug 26, 2013, 4:12:32 PM8/26/13
to rubyonra...@googlegroups.com
Hassan Schroeder wrote in post #1119612:
> On Mon, Aug 26, 2013 at 12:42 PM, Love U Ruby <li...@ruby-forum.com>
> wrote:
>>
>> My question is how should I get the hash {1=>2,3=>{4=>5,6=>7}} from that
>> string?
>
> Why don't you generate valid JSON in the first place?
>
> `{1=>2,3=>{4=>5,6=>7}}.to_json` would show you what the string
> should look like (and why your example is so broken).

In my case the hash is inside the string,but I want the hash back from
the string? :( I don't know how to do this...

Hassan Schroeder

unread,
Aug 26, 2013, 4:39:25 PM8/26/13
to rubyonrails-talk
On Mon, Aug 26, 2013 at 1:12 PM, Love U Ruby <li...@ruby-forum.com> wrote:

> In my case the hash is inside the string,but I want the hash back from
> the string? :( I don't know how to do this...

If you must use that format --

2.0.0-p247 :017 > str
=> "1=2,3=(4=5,6=7)"
2.0.0-p247 :018 > eval str.tr('()','{}').gsub(/=/,'=>').prepend('{').concat('}')
=> {1=>2, 3=>{4=>5, 6=>7}}
2.0.0-p247 :019 >

Tamara Temple

unread,
Aug 26, 2013, 5:06:17 PM8/26/13
to rubyonra...@googlegroups.com
There is no JSON here at all.

Given this:
> new_str = new_str.prepend("{") << "}"
> # => "{1=>2,3=>{4=>5,6=>7}}"

You have a string which represents a what a Hash looks like. Why not run it through eval and see what you get?

my_hash = eval(new_str)


Love U Ruby

unread,
Aug 26, 2013, 5:10:00 PM8/26/13
to rubyonra...@googlegroups.com
tamouse m. wrote in post #1119628:
I was trying to avoid `eval`. I tried also the `yaml`. But no luck :(

Rob Biedenharn

unread,
Aug 26, 2013, 8:41:46 PM8/26/13
to rubyonra...@googlegroups.com

On 2013-Aug-26, at 17:10 , Love U Ruby wrote:

> tamouse m. wrote in post #1119628:
>> On Aug 26, 2013, at 2:42 PM, Love U Ruby <li...@ruby-forum.com> wrote:
>>
>>
>> You have a string which represents a what a Hash looks like. Why not run
>> it through eval and see what you get?
>>
>> my_hash = eval(new_str)
>
> I was trying to avoid `eval`. I tried also the `yaml`. But no luck :(


If all your keys and values are just digits (i.e., String#to_i likes them), then you can easily avoid eval and yaml. Just make your own parser. Here are some "learning tests" to get you started. If you avoid scrolling down too far to see my "answer", then just make the tests pass and you're done!

Of course, you can also expand the tests to cover even more exotic hash keys and values, but if you go too far you've just reinvented YAML or JSON with different syntax.

-Rob


require 'minitest/autorun'

class TestSomeCrappyMarkupLanguage < Minitest::Test
def setup
@str = "1=2,3=(4=5,6=7)"
end

def test_nil
refute SomeCrappyMarkupLanguage.parse(nil)
end

def test_empty_string
assert_equal({}, SomeCrappyMarkupLanguage.parse(""))
end

def test_simple_hash
assert_equal({1=>2}, SomeCrappyMarkupLanguage.parse("1=2"))
end

def test_two_elements
assert_equal({4=>5,6=>7}, SomeCrappyMarkupLanguage.parse("4=5,6=7"))
end

def test_nested
expected = { 1 => 2, 3 => { 4 => 5, 6 => 7 } }
assert_equal expected, SomeCrappyMarkupLanguage.parse(@str)
end

end

# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...
# spoilers below...

class SomeCrappyMarkupLanguage
def self.parse(str)
return nil unless str
result = {}
str.scan(/(\d+)=((?:\([^\)]*\))|\d+),?/).each do |key,value|
key = key.to_i
value = value =~ /\A\d+\z/ ? value.to_i : parse(value)
result[key] = value
end
result
end
end


Love U Ruby

unread,
Aug 27, 2013, 3:55:31 AM8/27/13
to rubyonra...@googlegroups.com
Rob Biedenharn wrote in post #1119642:

@Rob - thanks for such an detailed answer.. :) I need to give some more
time on this...

> class SomeCrappyMarkupLanguage
> def self.parse(str)
> return nil unless str
> result = {}
> str.scan(/(\d+)=((?:\([^\)]*\))|\d+),?/).each do |key,value|
> key = key.to_i
> value = value =~ /\A\d+\z/ ? value.to_i : parse(value)
> result[key] = value
> end
> result
> end
> end

Reply all
Reply to author
Forward
0 new messages