ruby-on-railsrubyruby-on-rails-3hashmapruby-hash

How to remove a key from Hash and get the remaining hash in Ruby/Rails?


To add a new pair to Hash I do:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}

Is there a similar way to delete a key from Hash ?

This works:

{:a => 1, :b => 2}.reject! { |k| k == :a }   #=> {:b => 2}

but I would expect to have something like:

{:a => 1, :b => 2}.delete!(:a)   #=> {:b => 2}

It is important that the returning value will be the remaining hash, so I could do things like:

foo(my_hash.reject! { |k| k == my_key })

in one line.


Solution

  • For those of you who just came here to know how to delete a key/value pair from a hash, you can use:
    hash.delete(key)

    For the rest of you who came here to read a wall of text about something entirely different, you can read the rest of this answer:

    Rails has an except/except! method that returns the hash with those keys removed. If you're already using Rails, there's no sense in creating your own version of this.

    class Hash
      # Returns a hash that includes everything but the given keys.
      #   hash = { a: true, b: false, c: nil}
      #   hash.except(:c) # => { a: true, b: false}
      #   hash # => { a: true, b: false, c: nil}
      #
      # This is useful for limiting a set of parameters to everything but a few known toggles:
      #   @person.update(params[:person].except(:admin))
      def except(*keys)
        dup.except!(*keys)
      end
    
      # Replaces the hash without the given keys.
      #   hash = { a: true, b: false, c: nil}
      #   hash.except!(:c) # => { a: true, b: false}
      #   hash # => { a: true, b: false }
      def except!(*keys)
        keys.each { |key| delete(key) }
        self
      end
    end