Forum: Ruby how to make a[2][2][3]=4 work?

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.
Ba608f20b6707017d9812b9b3f1406e3?d=identicon&s=25 gpy good (gpygood)
on 2007-06-12 08:29
a=Hash.new{|h,k|
  h[k]={}
}

p a[1]=1

a[2][1]=2
 #a[2][2][3]=4
p a
Ba608f20b6707017d9812b9b3f1406e3?d=identicon&s=25 gpy good (gpygood)
on 2007-06-12 08:35
I know this can work,but I think it is suck
a=Hash.new{|h,k|
  h[k]=Hash.new{|h,k|h[k]=Hash.new{|h,k|h[k]={}}}
}

p a[1]=1

a[2][1]=2
a[2][2][3]=4
a[3][1][1][1]=1
p a
1c1e3bdfe006a22214102fcd6434a012?d=identicon&s=25 Daniel Sheppard (Guest)
on 2007-06-12 08:42
(Received via mailing list)
> p a
build_hash = proc {|h,k|h[k] = Hash.new &build_hash }
a = Hash.new &build_hash
934180817a3765d132193a5428f99051?d=identicon&s=25 Sylvain Joyeux (Guest)
on 2007-06-12 08:50
(Received via mailing list)
def recursive_hash
  Hash.new { |h, k| h[k] = recursive_hash }
end
a = recursive_hash

Or even

class Hash
  def self.recursive
    new { |h, k| h[k] = recursive }
  end
end

which gives

>> a = Hash.recursive
=>
>> a[1][2][3][4] = 1
=> 1
>> puts a.inspect
{1=>{2=>{3=>{4=>1}}}}
Cf6d0868b2b4c69bac3e6f265a32b6a7?d=identicon&s=25 Daniel Martin (Guest)
on 2007-06-12 14:23
(Received via mailing list)
In addition to what's already been posted, there's this, which doesn't
require any extra variables or methods:

a = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}

gz zz <gpygood@126.com> writes:

> a[2][1]=2
> a[2][2][3]=4
> a[3][1][1][1]=1
> p a

irb(main):001:0> a = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}
=> {}
irb(main):002:0> a[2][1]=2
=> 2
irb(main):003:0> a[2][2][3]=4
=> 4
irb(main):004:0> a[3][1][1][1]=1
=> 1
irb(main):005:0> p a
{2=>{1=>2, 2=>{3=>4}}, 3=>{1=>{1=>{1=>1}}}}
=> nil
88521907e2c9c585bc94e35a38893dc5?d=identicon&s=25 Jenda Krynicky (jendaperl)
on 2007-06-12 14:50
gz zz wrote:
> a=Hash.new{|h,k|
>   h[k]={}
> }
>
> p a[1]=1
>
> a[2][1]=2
>  #a[2][2][3]=4
> p a

Sure. Use Perl.

Oops, sorry. I forgot, datastructure autovivification is wrong,
variables springing into life (or maybe not, read the rest of the method
to find out) inadvertently are good.

Jenda
Ae16cb4f6d78e485b04ce1e821592ae5?d=identicon&s=25 Martin DeMello (Guest)
on 2007-06-12 15:25
(Received via mailing list)
On 6/12/07, Jenda Krynicky <jenda@cpan.org> wrote:
>
> Sure. Use Perl.
>
> Oops, sorry. I forgot, datastructure autovivification is wrong,
> variables springing into life (or maybe not, read the rest of the method
> to find out) inadvertently are good.

That's okay, it happens to the best of us.

martin
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-06-12 17:56
(Received via mailing list)
On Jun 12, 6:21 am, Daniel Martin <mar...@snowplow.org> wrote:
> In addition to what's already been posted, there's this, which doesn't
> require any extra variables or methods:
>
> a = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}

Thanks for this - I didn't know about the default_proc method. Quite
elegant in this case.
F1b2ecf88133598cfa5af4e792dd6f65?d=identicon&s=25 Fsormok Fsormok (fsormok)
on 2007-07-20 19:57
> Sure. Use Perl.

What's the ruby-way of such things?

e.g.:

   int[eth0][ip]   = "10.0.0.1"
   int[eth0][mask] = "255.255.255.0"
   int[eth0][cidr] = "24"
   int[eth1][ip]   = "10.0.1.1"
   int[eth1][mask] = "255.255.255.0"
   int[eth1][cidr] = "24"
   .
   .
   .

I like it if I have all these informations handy within one hash. But
even for me as a realy ruby-newby this looks much more like perl than
ruby.

It would be great to hear your thoughts how this would be done "the ruby
way"...

clean and elegant :-)

--fsormok
4feed660d3728526797edeb4f0467384?d=identicon&s=25 Bill Kelly (Guest)
on 2007-07-20 21:49
(Received via mailing list)
From: "Fsormok Fsormok" <fsormok@inbox.ru>
>   int[eth1][ip]   = "10.0.1.1"
> It would be great to hear your thoughts how this would be done "the ruby
> way"...
>
> clean and elegant :-)

You can do that in Ruby, if you want to.
See: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/...

irb(main):011:0> int = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}
=> {}
irb(main):012:0> int[:eth0][:ip]   = "10.0.0.1"
irb(main):013:0> int[:eth0][:mask] = "255.255.255.0"
irb(main):014:0> int[:eth0][:cidr] = "24"
irb(main):015:0> int[:eth1][:ip]   = "10.0.1.1"
irb(main):016:0> int[:eth1][:mask] = "255.255.255.0"
irb(main):017:0> int[:eth1][:cidr] = "24"
irb(main):018:0> int
=> {:eth0=>{:ip=>"10.0.0.1", :mask=>"255.255.255.0", :cidr=>"24"},
:eth1=>{:ip=>"10.0.1.1", :mask=>"255.255.255.0", :cidr=>"24"}}


Another possibility might be OpenStruct.

irb(main):026:0> require 'ostruct'
=> true
irb(main):027:0> int = Hash.new{|h,k| h[k]=OpenStruct.new}
=> {}
irb(main):028:0> int[:eth0].ip   = "10.0.0.1"
irb(main):029:0> int[:eth0].mask = "255.255.255.0"
irb(main):030:0> int[:eth0].cidr = "24"
irb(main):031:0> int[:eth1].ip   = "10.0.1.1"
irb(main):032:0> int[:eth1].mask = "255.255.255.0"
irb(main):033:0> int[:eth1].cidr = "24"
irb(main):034:0> int
=> {:eth0=>#<OpenStruct ip="10.0.0.1", mask="255.255.255.0", cidr="24">,
:eth1=>#<OpenStruct ip="10.0.1.1", mask="255.255.255.0",
cidr="24">}


Regards,

Bill
2ee1a7960cc761a6e92efb5000c0f2c9?d=identicon&s=25 William James (Guest)
on 2007-07-20 22:26
(Received via mailing list)
On Jun 12, 1:29 am, gz zz <gpyg...@126.com> wrote:
> a=Hash.new{|h,k|
>   h[k]={}
>
> }
>
> p a[1]=1
>
> a[2][1]=2
>  #a[2][2][3]=4


a = {}
    ==>{}
a[1] = 1
    ==>1
a[ [2,1] ] = 2
    ==>2
a[ [2,2,3] ] = 4
    ==>4
p a
{[2, 2, 3]=>4, [2, 1]=>2, 1=>1}
    ==>nil
F1b2ecf88133598cfa5af4e792dd6f65?d=identicon&s=25 Fsormok Fsormok (fsormok)
on 2007-07-23 09:15
> a = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}

> irb(main):026:0> require 'ostruct'
> irb(main):027:0> int = Hash.new{|h,k| h[k]=OpenStruct.new}

>a = {}
>    ==>{}
>a[1] = 1
>    ==>1
>a[ [2,1] ] = 2
>    ==>2
>a[ [2,2,3] ] = 4
>    ==>4
>p a
>{[2, 2, 3]=>4, [2, 1]=>2, 1=>1}
>    ==>nil

Tanks for the replies.

I'm just a little bit confused because in ruby everything is lean and
clean but when it comes to hashes of hashes it gets kind of complicated.
For me it looks like ruby has another "concept" of solving such things.

-fsormok
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-07-26 00:45
(Received via mailing list)
On 7/23/07, Fsormok Fsormok <fsormok@inbox.ru> wrote:
> >    ==>2
> For me it looks like ruby has another "concept" of solving such things.
>

Hmm the context of this statement seems not complete in *this* thread,
maybe you could elaborate on this a little bit?
Personally I feel that Ruby's concept of Hashes is clearcut and
exactly the same as in most of its relatives (Perl,Python...).

What exactly would you like to have "simpler"?

Cheers
Robert
Bd2d12f85f54f93d3c9e2f558a593024?d=identicon&s=25 Mark Thomas (markthomas)
on 2007-07-26 00:45
(Received via mailing list)
On Jul 20, 1:57 pm, Fsormok Fsormok <fsor...@inbox.ru> wrote:
>    int[eth1][mask] = "255.255.255.0"
> way"...
>
> clean and elegant :-)

In my personal opinion, multilevel hashes aren't clean and elegant in
any language. I'd try to make an object out of it:

class Interface
  attr_accessor :name, :ip, :mask, :cidr
end

i = Interface.new
i.name = "eth0"
i.ip = "10.0.0.1"
i.mask = "255.255.255.0"
i.cidr = 24

- Mark.
F1b2ecf88133598cfa5af4e792dd6f65?d=identicon&s=25 Fsormok Fsormok (fsormok)
on 2007-07-31 11:41
Thanx Mark

This is exactly what i liked to hear :-)

> In my personal opinion, multilevel hashes aren't clean and elegant in
> any language.

HoH are quiet common in perl (at least I use them alot), not in Ruby
IMHO.

But as always: TMTOWTDI

> I'd try to make an object out of it:
>
> class Interface
>   attr_accessor :name, :ip, :mask, :cidr
> end
>
> i = Interface.new
> i.name = "eth0"
> i.ip = "10.0.0.1"
> i.mask = "255.255.255.0"
> i.cidr = 24
>
> - Mark.
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (Guest)
on 2007-07-31 11:47
(Received via mailing list)
2007/7/23, Fsormok Fsormok <fsormok@inbox.ru>:
> >    ==>2
> For me it looks like ruby has another "concept" of solving such things.
Its this what you are looking for?

$ ruby <<XXX
> miss = lambda {|h,k| h[k] = Hash.new(&miss)}
> hash = Hash.new(&miss)
> hash[1][2]=3
> hash[4]=5
> p hash
> XXX
{1=>{2=>3}, 4=>5}

Kind regards

robert
Bc7e893b6d4605000478c871b7ce8862?d=identicon&s=25 Gabe Da silveira (dasil003)
on 2009-04-02 18:25
Daniel Martin wrote:
> In addition to what's already been posted, there's this, which doesn't
> require any extra variables or methods:
>
> a = Hash.new{|h,k| h[k]=Hash.new &h.default_proc}

That's clever, but I think the way it automatically creates keys is
wrong.  You need to be able to check to see if a key exists without
polluting the hash with a bunch of empties.

Hence my new gem:

http://github.com/dasil003/safe-nested-hash
This topic is locked and can not be replied to.