How to add to an existing hash in Ruby

224,833

Solution 1

If you have a hash, you can add items to it by referencing them by key:

hash = { }
hash[:a] = 'a'
hash[:a]
# => 'a'

Here, like [ ] creates an empty array, { } will create a empty hash.

Arrays have zero or more elements in a specific order, where elements may be duplicated. Hashes have zero or more elements organized by key, where keys may not be duplicated but the values stored in those positions can be.

Hashes in Ruby are very flexible and can have keys of nearly any type you can throw at it. This makes it different from the dictionary structures you find in other languages.

It's important to keep in mind that the specific nature of a key of a hash often matters:

hash = { :a => 'a' }

# Fetch with Symbol :a finds the right value
hash[:a]
# => 'a'

# Fetch with the String 'a' finds nothing
hash['a']
# => nil

# Assignment with the key :b adds a new entry
hash[:b] = 'Bee'

# This is then available immediately
hash[:b]
# => "Bee"

# The hash now contains both keys
hash
# => { :a => 'a', :b => 'Bee' }

Ruby on Rails confuses this somewhat by providing HashWithIndifferentAccess where it will convert freely between Symbol and String methods of addressing.

You can also index on nearly anything, including classes, numbers, or other Hashes.

hash = { Object => true, Hash => false }

hash[Object]
# => true

hash[Hash]
# => false

hash[Array]
# => nil

Hashes can be converted to Arrays and vice-versa:

# Like many things, Hash supports .to_a
{ :a => 'a' }.to_a
# => [[:a, "a"]]

# Hash also has a handy Hash[] method to create new hashes from arrays
Hash[[[:a, "a"]]]
# => {:a=>"a"} 

When it comes to "inserting" things into a Hash you may do it one at a time, or use the merge method to combine hashes:

{ :a => 'a' }.merge(:b => 'b')
# {:a=>'a',:b=>'b'}

Note that this does not alter the original hash, but instead returns a new one. If you want to combine one hash into another, you can use the merge! method:

hash = { :a => 'a' }

# Returns the result of hash combined with a new hash, but does not alter
# the original hash.
hash.merge(:b => 'b')
# => {:a=>'a',:b=>'b'}

# Nothing has been altered in the original
hash
# => {:a=>'a'}

# Combine the two hashes and store the result in the original
hash.merge!(:b => 'b')
# => {:a=>'a',:b=>'b'}

# Hash has now been altered
hash
# => {:a=>'a',:b=>'b'}

Like many methods on String and Array, the ! indicates that it is an in-place operation.

Solution 2

my_hash = {:a => 5}
my_hash[:key] = "value"

Solution 3

If you want to add more than one:

hash = {:a => 1, :b => 2}
hash.merge! :c => 3, :d => 4
p hash

Solution 4

x = {:ca => "Canada", :us => "United States"}
x[:de] = "Germany"
p x

Solution 5

You can use double splat operator which is available since Ruby 2.0:

h = { a: 1, b: 2 }
h = { **h, c: 3 }
p h
# => {:a=>1, :b=>2, :c=>3}
Share:
224,833

Related videos on Youtube

Tom
Author by

Tom

Updated on June 23, 2020

Comments

  • Tom
    Tom about 4 years

    In regards to adding an key => value pair to an existing populated hash in Ruby, I'm in the process of working through Apress' Beginning Ruby and have just finished the hashes chapter.

    I am trying to find the simplest way to achieve the same results with hashes as this does with arrays:

    x = [1, 2, 3, 4]
    x << 5
    p x
    
  • Tom
    Tom almost 13 years
    I've tried to implement this with the following: x['key'] = "value" however I am receiving errors. I should mention I am working with strings.
  • tadman
    tadman almost 13 years
    What's the error? It could be anything unless you are more specific.
  • danh
    danh almost 11 years
    A lot of valuable information, but lacking the most basic formulation as answered so simply by @robbrit.
  • Stephan
    Stephan almost 10 years
    Please edit your answer to actually answer the question that was asked, somewhere near the top preferably. It would be rude of me to do it for you.
  • tadman
    tadman almost 10 years
    @Stephan Added a more concise example at the top.
  • Anas Ansari
    Anas Ansari about 2 years
    It doesn't work now: line_item[:brain] = "HELLO" Raises error: can't write unknown attribute brain
  • Anas Ansari
    Anas Ansari about 2 years
    It doesn't work: line_item[:brain] = "HELLO" Raises error: can't write unknown attribute brain
  • Anas Ansari
    Anas Ansari about 2 years
    IT doesn't work: line_item.merge({line_total: "YYEYAH"}). Raises: undefined method `merge' Line_item.
  • Jeremy Roman
    Jeremy Roman about 2 years
    @AnasAnsari it seems like line_item isn't a Hash in your code