Forum: Ruby string to hash

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B9638176195f247741cbbb85a2ab44c8?d=identicon&s=25 Jens -- (jc71229)
on 2008-12-08 18:51
Hi All,

I am in the need of a method that does the following:

get 2 arguments a string and an integer (int_val).
The string has the following form "a.b.c.d"

the method should return a nested hash like that:

{ :a => { :b => { :c => { :d => int_val } } } }

Hmmmm I am not rubyist enough to solve that elegant (or not at all :-/).

Thanks
Jens
5d06917e13b29bcff1c1609492c06873?d=identicon&s=25 Dave Thomas (Guest)
on 2008-12-08 19:02
(Received via mailing list)
On Dec 8, 2008, at 11:44 AM, Jens -- wrote:

> I am in the need of a method that does the following:
>
> get 2 arguments a string and an integer (int_val).
> The string has the following form "a.b.c.d"
>
> the method should return a nested hash like that:
>
> { :a => { :b => { :c => { :d => int_val } } } }

How about

def nested_hash(string, val)
   string.split(/\./).reverse.inject(val) { |accum, val| { val.to_sym
=> accum } }
end

p nested_hash("a.b.c.d", 123)
B9638176195f247741cbbb85a2ab44c8?d=identicon&s=25 Jens -- (jc71229)
on 2008-12-08 19:27
>
> def nested_hash(string, val)
>    string.split(/\./).reverse.inject(val) { |accum, val| { val.to_sym
> => accum } }
> end
>
> p nested_hash("a.b.c.d", 123)

Hmmmmmm ... that wasn't as hard as I expected it.
Anyway I am impressed how fast that has been solved.

Thanks a lot David!
B9638176195f247741cbbb85a2ab44c8?d=identicon&s=25 Jens -- (jc71229)
on 2008-12-08 19:28
Oh sorry! Dave ... I have your book :-)
8666d1ebabcea440585dfe831a4af9f1?d=identicon&s=25 Brian Adkins (Guest)
on 2008-12-09 20:40
(Received via mailing list)
Jens -- <jens@carroll.de> writes:

>
> Hmmmm I am not rubyist enough to solve that elegant (or not at all :-/).

Dave's solution is a good one & "idiomatic Ruby", and it should be
efficient since it spends much time in C code.

The following is another perspective that may or may not be clearer to
you depending on your comfort level with recursion:

require 'pp'

def tail list
  list[1..-1]
end

def nested_hash list, val
  return val if list.empty?
  { list.first.to_sym => nested_hash(tail(list), val) }
end

pp nested_hash("a.b.c.d".split('.'), 7)

==> {:a=>{:b=>{:c=>{:d=>7}}}}
E088bb5c80fd3c4fd02c2020cdacbaf0?d=identicon&s=25 Jesús Gabriel y Galán (Guest)
on 2008-12-15 15:11
(Received via mailing list)
On Tue, Dec 9, 2008 at 8:33 PM, Brian Adkins <lojicdotcom@gmail.com>
wrote:
>>
>> { :a => { :b => { :c => { :d => int_val } } } }
>>
>> Hmmmm I am not rubyist enough to solve that elegant (or not at all :-/).
>
> Dave's solution is a good one & "idiomatic Ruby", and it should be
> efficient since it spends much time in C code.

Sorry to answer after so long, but I wanted to give another version:

irb(main):059:0> def nested_hash s, i
irb(main):060:1> hash = Hash.new {|h,k| h[k] =
Hash.new(&h.default_proc)}
irb(main):061:1> terms = s.split(".")
irb(main):062:1> temp = terms[0..-2].inject(hash) {|acc,val|
acc[val.to_sym]}
irb(main):063:1> temp[terms[-1].to_sym] = i
irb(main):064:1> hash
irb(main):065:1> end
=> nil
irb(main):066:0> nested_hash "a.b.c.d", 55
=> {:a=>{:b=>{:c=>{:d=>55}}}}

I am so fond of the arbitrarily nested hash construct :-).

Jesus.
This topic is locked and can not be replied to.