----- Original Message ----- 
From: "Jason Persampieri" <jason / persampieri.net>
To: "ruby-talk ML" <ruby-talk / ruby-lang.org>
Sent: Thursday, December 05, 2002 2:42 PM
Subject: Hash 'issues'


> OK, I'm messing around with hashes for the first time,
> and I've hit a (very) small bump.
> 
> Let's say I have a an array where each line contains
> key=value.  Also, assume that there can be duplicate
> keys and if so, the final 'value' should be an array.
> 
> In theory, I'd like to 'each' through the array and
> fill the hash like this...
> 
> foo = Hash.new
> data.each {|line|
>   line =~ /^(.*)=(.*)$/
>   key, value = $1.split, $2.split  # so far, so good
> 
>   foo[key].push(value)
> }
> 
> Now, there are two problems with this.  
> 
> (1) << (or .push) doesn't change the array... I have

Array#push and Array#<< DO change the receiver.

a  = [1, 2, 3]
a.size ==> 3
a.push(4) ==> [1, 2, 3, 4]
a.size ==> 4
a.push([5,6] ==> [1, 2, 3, 4, [5, 6]]
a.size ==> 5

> to do foo[key] = foo[key].push(value).  This is ok,
> but wouldn't it make sense to have <<= or .push!
> methods?  But this is completeness stuff and obviously
> not a priority for Matz.
> 
> (2) << (or .push) doesn't know what to do if foo[key]
> is nil (since it doesn't know it's of type Array).  No
> problem, I think to myself... I'll just declare foo as
> foo=Hash.new([]).  Of course, this doesn't work since

(foo[key] ||= []).push(value)

> now, ALL keys point to the SAME array... if I modify
> one, I modify all of them...doh!  I know I COULD do a
> check to see if the value is nil or not, but that gets
> a little messy.  I guess what would be nice is if I
> could specify that this is a Hash of Arrays (or
> whatever) during instantiation without the defining of
> a default value... something like foo=Hash.new(Array).
> 
> Anyone have a better solution?
> 
> Jason
> 
> 
>