show me the ruby way

N

nord ehacedod

This works, but there must be a more natural way to do
this. Can someone point the way?

Thanks,
-
nord

#!/bin/ruby

class HashAutoVivify < Hash

# create sub-hashes automatically
def [](n)
self[n]=HashAutoZero.new if super(n)==nil
super(n)
end

# "values" in sub-hash automatically have initial
value 0
class HashAutoZero < Hash
def [](n)
self[n]=0 if super(n)==nil
super(n)
end
end

def printSortedBy(sortSpecifier='keys')
puts "---- sorted by #{sortSpecifier}"
self.keys.sort.each do | m |
puts m
if sortSpecifier == 'keys'
self[m].keys.sort_by {|a| a }.each do | k |
puts " #{k.ljust(12)} #{self[m][k]}"
end
elsif sortSpecifier == 'vals'
self[m].keys.sort_by {|a| -self[m][a] }.each
do | k |
puts " #{k.ljust(12)} #{self[m][k]}"
end
end
end
end

def printByKeys
printSortedBy('keys')
end

def printByVals
printSortedBy('vals')
end
end


metaData = HashAutoVivify.new
metaData['fruit']['apple'] = 13
metaData['fruit']['mango'] = 7
metaData['fruit']['banana'] = 11
metaData['fruit']['cherry'] = 17
metaData['veg']['eggplant'] = 7
metaData['veg']['artichoke'] += 19
metaData['veg']['green bean'] -= 5
metaData['veg']['squash'] += 2
metaData.printByKeys
metaData.printByVals


__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com
 
T

ts

n> metaData = HashAutoVivify.new

try this (only with ruby-1.8)

metaData = Hash.new {|h, k| h[k] = Hash.new(0) }

when ruby try to access a key which is not defined, it call the block with
(hash, key), you store in hash[key] a new hash with `0' as default value



Guy Decoux
 
B

Brian Candler

This works, but there must be a more natural way to do
this. Can someone point the way?

There's a new feature in 1.8.0 for it:
# create sub-hashes automatically
def [](n)
self[n]=HashAutoZero.new if super(n)==nil
super(n)
end

h = Hash.new { |me,k| me[k]={} }
# "values" in sub-hash automatically have initial
value 0
class HashAutoZero < Hash
def [](n)
self[n]=0 if super(n)==nil
super(n)
end
end

h2 = Hash.new(0)

although this means that unset values read out as 0, it does not autovivify
the value in the hash. If you need that, then:

h2 = Hash.new { |me,k| me[k]=0 }

Combining these two:

irb(main):020:0> h = Hash.new { |h1,k1| h1[k1] = Hash.new { |h2,k2| h2[k2]=0 } }
=> {}
irb(main):021:0> h['fred']
=> {}
irb(main):022:0> h
=> {"fred"=>{}}
irb(main):023:0> h['foo']['bar']
=> 0
irb(main):024:0> h
=> {"fred"=>{}, "foo"=>{"bar"=>0}}

Regards,

Brian.
 
A

Alan Chen

ts said:
try this (only with ruby-1.8)

metaData = Hash.new {|h, k| h[k] = Hash.new(0) }

when ruby try to access a key which is not defined, it call the block with
(hash, key), you store in hash[key] a new hash with `0' as default value

On a related note, with ruby 1.8.0 (2003-08-04) [i386-mswin32],
I was wondering about this behavior:

md = Hash.new { |h,k| h[h] = 0; 3 }
p md[1] # => 3
p md[1] # => 0

I understand that the first "p md[1]" is returning the result of the
block; is that intentional?

Cheers,
alan
 
J

Jason Creighton

On 2 Sep 2003 14:21:46 -0700
ts said:
try this (only with ruby-1.8)

metaData = Hash.new {|h, k| h[k] = Hash.new(0) }

when ruby try to access a key which is not defined, it call the block with
(hash, key), you store in hash[key] a new hash with `0' as default value

On a related note, with ruby 1.8.0 (2003-08-04) [i386-mswin32],
I was wondering about this behavior:

md = Hash.new { |h,k| h[h] = 0; 3 }
p md[1] # => 3
p md[1] # => 0

I understand that the first "p md[1]" is returning the result of the
block; is that intentional?

~$ ri Hash.new
This is a test 'ri'. Please report errors and omissions
on http://www.rubygarden.org/ruby?RIOnePointEight

-------------------------------------------------------------- Hash::new
Hash.new -> aHash
Hash.new( anObject ) -> aHash
Hash.new {| aHash, key | block } -> aHash
------------------------------------------------------------------------
Returns a new, empty hash. If this hash is subsequently accessed by
a key that doesn't correspond to a hash entry, the value returned
depends on the style of new used to create the hash. In the first
form, the access returns nil. If anObject is specified, this single
object will be used for all default values. If a block is
specified, it will be called with the hash object and the key, and
should return the default value. It is the block's responsibility
to store the value in the hash if required.
h = Hash.new("Go Fish")
h["a"] = 100
h["b"] = 200
h["a"] #=> 100
h["c"] #=> "Go Fish"
# The following alters the single default object
h["c"].upcase! #=> "GO FISH"
h["d"] #=> "GO FISH"
h.keys #=> ["a", "b"]
# While this creates a new default object each time
h = Hash.new { |hash, key| hash[key] = "Go Fish: #{key}" }
h["c"] #=> "Go Fish: c"
h["c"].upcase! #=> "GO FISH: C"
h["d"] #=> "Go Fish: d"
h.keys #=> ["c", "d"]

~$

So yes, I think it is intentional.

Jason Creighton
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,781
Messages
2,569,619
Members
45,314
Latest member
HugoKeogh

Latest Threads

Top