Search code examples
rubyhash

How do I extract a sub-hash from a hash?


I have a hash:

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}

What is the best way to extract a sub-hash like this?

h1.extract_subhash(:b, :d, :e, :f) # => {:b => :B, :d => :D}
h1 #=> {:a => :A, :c => :C}

Solution

  • If you specifically want the method to return the extracted elements but h1 to remain the same:

    h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
    h2 = h1.select {|key, value| [:b, :d, :e, :f].include?(key) } # => {:b=>:B, :d=>:D} 
    h1 = Hash[h1.to_a - h2.to_a] # => {:a=>:A, :c=>:C} 
    

    And if you want to patch that into the Hash class:

    class Hash
      def extract_subhash(*extract)
        h2 = self.select{|key, value| extract.include?(key) }
        self.delete_if {|key, value| extract.include?(key) }
        h2
      end
    end
    

    If you just want to remove the specified elements from the hash, that is much easier using delete_if.

    h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
    h1.delete_if {|key, value| [:b, :d, :e, :f].include?(key) } # => {:a=>:A, :c=>:C} 
    h1  # => {:a=>:A, :c=>:C}