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

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


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  endend


Oneliner plain ruby, it works only with ruby > 1.9.x:

1.9.3p0 :002 > h = {:a => 1, :b => 2} => {:a=>1, :b=>2} 1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) } => {:b=>2} 

Tap method always return the object on which is invoked...

Otherwise if you have required active_support/core_ext/hash (which is automatically required in every Rails application) you can use one of the following methods depending on your needs:

➜  ~  irb1.9.3p125 :001 > require 'active_support/core_ext/hash' => true 1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3} => {:a=>1, :b=>2, :c=>3} 1.9.3p125 :003 > h.except(:a) => {:b=>2, :c=>3} 1.9.3p125 :004 > h.slice(:a) => {:a=>1} 

except uses a blacklist approach, so it removes all the keys listed as args, while slice uses a whitelist approach, so it removes all keys that aren't listed as arguments. There also exist the bang version of those method (except! and slice!) which modify the given hash but their return value is different both of them return an hash. It represents the removed keys for slice! and the keys that are kept for the except!:

1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a) => {:b=>2, :c=>3} 1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a) => {:b=>2, :c=>3} 


Why not just use:

hash.delete(key)

hash is now the "remaining hash" you're looking for.