Append key/value pair to hash with << in Ruby
In Ruby, one can append values to existing arrays using <<:
a = []
a << "foo"
but, can you also append key/value pairs to an existing hash?
h = {}
h << :key "bar"
I know you can do:
h[:key] = ""
h[:key] << "bar"
but that's not I want.
Thanks.
There is merge!
.
h = {}
h.merge!(key: "bar")
# => {:key=>"bar"}
Since hashes aren't inherently ordered, there isn't a notion of appending. Ruby hashes since 1.9 maintain insertion order, however. Here are the ways to add new key/value pairs.
The simplest solution is
h[:key] = "bar"
If you want a method, use store
:
h.store(:key, "bar")
If you really, really want to use a "shovel" operator (<<
), it is actually appending to the value of the hash as an array, and you must specify the key:
h[:key] << "bar"
The above only works when the key exists. To append a new key, you have to initialize the hash with a default value, which you can do like this:
h = Hash.new {|h, k| h[k] = ''}
h[:key] << "bar"
You may be tempted to monkey patch Hash to include a shovel operator that works in the way you've written:
class Hash
def <<(k,v)
self.store(k,v)
end
end
However, this doesn't inherit the "syntactic sugar" applied to the shovel operator in other contexts:
h << :key, "bar" #doesn't work
h.<< :key, "bar" #works
No, I don't think you can append key/value pairs. The only thing closest that I am aware of is using the store
method:
h = {}
h.store("key", "value")
Perhaps you want Hash#merge ?
1.9.3p194 :015 > h={}
=> {}
1.9.3p194 :016 > h.merge(:key => 'bar')
=> {:key=>"bar"}
1.9.3p194 :017 >
If you want to change the array in place use merge!
1.9.3p194 :016 > h.merge!(:key => 'bar')
=> {:key=>"bar"}
Similar as they are, merge!
and store
treat existing hashes differently depending on keynames, and will therefore affect your preference. Other than that from a syntax standpoint, merge!
's key: "value"
syntax closely matches up against JavaScript and Python. I've always hated comma-separating key-value pairs, personally.
hash = {}
hash.merge!(key: "value")
hash.merge!(:key => "value")
puts hash
{:key=>"value"}
hash = {}
hash.store(:key, "value")
hash.store("key", "value")
puts hash
{:key=>"value", "key"=>"value"}
To get the shovel operator <<
working, I would advise using Mark Thomas's answer.