I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):
h = Hash.new(Hash.new(0))
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
p h["a"]["b"] => 2
p h["a"]["c"] => 1
p h.class => Hash
p h["a"].class => Hash
p h["a"]["b"].class => Fixnum
p h => {}
What's wrong?
Lars
···
--
Posted via http://www.ruby-forum.com/.
Changing declaration by
h = Hash.new {|h,k| h[k] = Hash.new(0) }
makes things ok. What are the difference beetween the two declaration?
Lars
···
--
Posted via http://www.ruby-forum.com/.
Try this definition:
h = Hash.new { |h, k|
h[k] = Hash.new(0)
}
It will actually modify 'h' rather than simply returning and modifying the default value.
Gennady.
···
list-bounce@example.com wrote:
I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they
appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):
h = Hash.new(Hash.new(0))
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
p h["a"]["b"] => 2
p h["a"]["c"] => 1
p h.class => Hash
p h["a"].class => Hash
p h["a"]["b"].class => Fixnum
p h => {}
What's wrong?
Lars
You're using the wrong form of Hash.new for this use case.
Hash.new(default)
gives you a hash which simply returns default from [key] when key
doesn't exist, it leaves the hash itself alone.
You need to use a block
h = Hash.new {|h, k| h[k] = Hash.new(0)}
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
h["a"]["b"] # => 2
h["a"]["c"] # => 1
h.class # => Hash
h # => {"a"=>{"b"=>2, "c"=>1}}
···
On 10/29/07, Lars Ticot <nicolas.rassat@free.fr> wrote:
I try to get a hash of hash to make some sort of counter (I have a set
of random pair and want to count the number of times they appear). I use
this code but even if I can access data, my hash seems empty (so each
and the others don't work):
h = Hash.new(Hash.new(0))
h["a"]["b"] += 1
h["a"]["b"] += 1
h["a"]["c"] += 1
p h["a"]["b"] => 2
p h["a"]["c"] => 1
p h.class => Hash
p h["a"].class => Hash
p h["a"]["b"].class => Fixnum
p h => {}
What's wrong?
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
Lars Ticot wrote:
h = Hash.new(Hash.new(0))
Changing declaration by
h = Hash.new {|h,k| h[k] = Hash.new(0) }
makes things ok. What are the difference beetween the two declaration?
There are two differences:
First: The first version executes "Hash.new(0)" once (before the outer
Hash.new is called, since parameters are evaluated before the actual method
call (obviously)) and stores the result as the default value. This means that
if you do something like h[:foo][:chunky] = "bacon" and h[:foo] has not been
assigned before, you will actually change the default value, so h[:bar]
[:chunky] will also be "bacon". The second version just stores the block and
executes it everytime a key that hasn't been assigned before is accessed.
Second: The second version has "h[k] =" in it, so it will not only return the
newly created hash, it will also store it in the outer hash. The first
version won't do that, which means that h will always appear as empty until
you do any actual assignments to it.
HTH,
Sebastian
···
--
Jabber: sepp2k@jabber.org
ICQ: 205544826
Sebastian Hungerecker wrote:
There are two differences:
[...]
Thanks all of you guys and especially Sebastian for the explanations.
Lars
···
--
Posted via http://www.ruby-forum.com/\.