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

前端 未结 15 1823
梦如初夏
梦如初夏 2020-12-04 04:26

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 simi

相关标签:
15条回答
  • 2020-12-04 05:02

    Instead of monkey patching or needlessly including large libraries, you can use refinements if you are using Ruby 2:

    module HashExtensions
      refine Hash do
        def except!(*candidates)
          candidates.each { |candidate| delete(candidate) }
          self
        end
    
        def except(*candidates)
          dup.remove!(candidates)
        end
      end
    end
    

    You can use this feature without affecting other parts of your program, or having to include large external libraries.

    class FabulousCode
      using HashExtensions
    
      def incredible_stuff
        delightful_hash.except(:not_fabulous_key)
      end
    end
    
    0 讨论(0)
  • 2020-12-04 05:04

    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:

    ➜  ~  irb
    1.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} 
    
    0 讨论(0)
  • 2020-12-04 05:04

    If you want to use pure Ruby (no Rails), don't want to create extension methods (maybe you need this only in one or two places and don't want to pollute namespace with tons of methods) and don't want to edit hash in place (i.e., you're fan of functional programming like me), you can 'select':

    >> x = {:a => 1, :b => 2, :c => 3}
    => {:a=>1, :b=>2, :c=>3}
    >> x.select{|x| x != :a}
    => {:b=>2, :c=>3}
    >> x.select{|x| ![:a, :b].include?(x)}
    => {:c=>3}
    >> x
    => {:a=>1, :b=>2, :c=>3}
    
    0 讨论(0)
  • 2020-12-04 05:04

    It's was great if delete return the delete pair of the hash. I'm doing this:

    hash = {a: 1, b: 2, c: 3}
    {b: hash.delete(:b)} # => {:b=>2}
    hash  # => {:a=>1, :c=>3} 
    
    0 讨论(0)
  • 2020-12-04 05:09

    This would also work: hash[hey] = nil

    0 讨论(0)
  • 2020-12-04 05:12

    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
    
    0 讨论(0)
提交回复
热议问题