i am still learning. in the below code @attributes is a hash table. i
want to add a new value 'a' for a key represented by 'a.key'. i also
want to group values with the same keys in to arrays. thanks for any
help.
konstantin
if @attributes.has_key?(a.key)
if @attributes[a.key].is_a?(Array) @attributes[a.key] << a
else @attributes[a.key] = [@attributes[a.key], a]
end
else @attributes[a.key] = a
end
Pardon my question, but isn't the whole point of hashes that every key is
unique?
···
On 11/22/05, ako... <akonsu@gmail.com> wrote:
hello,
i am still learning. in the below code @attributes is a hash table. i
want to add a new value 'a' for a key represented by 'a.key'. i also
want to group values with the same keys in to arrays. thanks for any
help.
konstantin
if @attributes.has_key?(a.key)
if @attributes[a.key].is_a?(Array) @attributes[a.key] << a
else @attributes[a.key] = [@attributes[a.key], a]
end
else @attributes[a.key] = a
end
def add(key, val)
if $hash.has_key?(key)
if $hash[key].is_a?(Array)
$hash[key] << val
else
$hash[key] = [$hash[key], val]
end
else
$hash[key] = val
end
end
def add2(key, val)
if $hash.has_key?(key)
$hash[key].to_a << val
else
$hash[key] = val.to_a
end
end
key = "a"
val = "aval"
add2(key, val)
puts $hash.inspect
key = "a"
val = "aval2"
add2(key, val)
puts $hash.inspect
This is a fairly standard Ruby idiom (a hash of arrays):
(@attributes[a.key]||=)<<a
What the above is doing is setting the entry for a.key to an empty
array if nothing exists, otherwise it will return the array already at
that location. Then the element a is added to that array.
Ryan
···
On 11/22/05, ako... <akonsu@gmail.com> wrote:
hello,
i am still learning. in the below code @attributes is a hash table. i
want to add a new value 'a' for a key represented by 'a.key'. i also
want to group values with the same keys in to arrays. thanks for any
help.
konstantin
if @attributes.has_key?(a.key)
if @attributes[a.key].is_a?(Array) @attributes[a.key] << a
else @attributes[a.key] = [@attributes[a.key], a]
end
else @attributes[a.key] = a
end
i am still learning. in the below code @attributes is a hash table. i
want to add a new value 'a' for a key represented by 'a.key'. i also
want to group values with the same keys in to arrays. thanks for any
help.
if @attributes.has_key?(a.key)
if @attributes[a.key].is_a?(Array) @attributes[a.key] << a
else @attributes[a.key] = [@attributes[a.key], a]
end
else @attributes[a.key] = a
end
An alternate approach might be:
@attributes = Hash.new {|h,k| h[k] = Array.new}
This will automatically create arrays to hold your keys, on demand.
yes, this is the point of hashes. in my program, i have attributes with
names (keys). i want to collect these attributes in to a data
structure. attributes with the same names form an array. like in a HTTP
POST form, if you have fields with the same names they are treated as
an array.
thank you. this assumes that the hash's default value is nil. but this
is a good enough assumption for my purposes. i was hoping to avoid
creating one-element arrays and still have the simplicity of a single
line solution but i guess this cant be done. thanks for your help.
Hey, thanks for that! I had no idea that the block form of Hash creation had block arguments. Sure it's in 'ri', but who looks there?
I often see people suggesting:
Hash.new{ }
without realizing that this doesn't set the value on the hash, just returns a blank array. I've never been able to use the block constructor syntax because it was so useless (because I also didn't know that <<= was a valid compound method).
In my opinion it is better to just put all the attributes into an
array (which is what my code does), even the single ones, that way you
can treat all the hashtable entries the same way (since they will all
be arrays.)
Ryan
···
On 11/22/05, ako... <akonsu@gmail.com> wrote:
yes, this is the point of hashes. in my program, i have attributes with
names (keys). i want to collect these attributes in to a data
structure. attributes with the same names form an array. like in a HTTP
POST form, if you have fields with the same names they are treated as
an array.
Note that a "Ruby" hint would be to get rid of your "is_a?", preferring to use "respond_to?" instead.
You could get fancier and just call "<<" on everything, catching exceptions and handling them for objects that don't implement that method.
Caleb
···
On Nov 22, 2005, at 5:42 PM, ako... wrote:
thank you. this assumes that the hash's default value is nil. but this
is a good enough assumption for my purposes. i was hoping to avoid
creating one-element arrays and still have the simplicity of a single
line solution but i guess this cant be done. thanks for your help.
Personally, I would keep every element of the hash an array. You can do that
like so...
def add4( key, value ) @hsh[key] = @hsh[key].to_a<<value
end
if you must keep entries in the hash that only have one value as single
elements and not as arrays..
def add5( key, value ) @hsh[key] = @hsh[key]?@hsh[key].to_a<<value:value
end