I am now trying for some hours to remove a nested hash key of a hash list. I saw many solution non-nested hashs wich looks like this:
   sample_hash = {"key1" => "value1", "key2" => "value2"}
   sample_hash.except("key1") 
This results in:
  {"key2"=>"value2"}
But if I try to use the except method on a hash with nested key then it doesn't work. Here my code:
  nested_hash = {"key1"=>"value1", "key2"=>{
                                           "nested_key1"=>"nestedvalue1",
                                           "nested_key2"=>"nestedvalue2"
                                           }
                }
  nested_hash.except("nested_key2")
The except() method returns the nested_hash without any changes. I have looked for a solution how I can pass nested hash-keys to the except method, but couldn't find anything. Is it even possible to pass nested keys to this method or should I use some other method which deletes a nested hash key from my hash list?
The delete function is the only way to remove a specific entry from a hash. Once you've deleted a key, it no longer shows up in a keys list or an each iteration, and exists will return false for that key.
what about
Hash[nested_hash.map {|k,v| [k,(v.respond_to?(:except)?v.except("nested_key2"):v)] }]
=> {"key1"=>"value1", "key2"=>{"nested_key1"=>"nestedvalue1"}}
ugh.
The accepted solution is valid for the scenario given but if you're looking for something that will do this for arbitrarily nested hash tables then you're going to need a recursive solution. I couldn't find a suitable solution anywhere, so I wrote one here.
Reproduced here with annotations:
class Hash
  def except_nested(key)
    r = Marshal.load(Marshal.dump(self)) # deep copy the hashtable
    r.except_nested!(key)
  end
  def except_nested!(key)
    self.except!(key)
    self.each do |_, v| # essentially dfs traversal calling except!
      v.except_nested!(key) if v.is_a?(Hash)
    end
  end
end
adding it to the Hash class so that you can call it the same way you call except/except! anywhere else.
t = { a: '1', b: { c: '3', d: '4' } } 
r = t.except_nested(:c) 
# r => {:a=>"1", :b=>{:d=>"4"}}
# t => {:a=>"1", :b=>{:c=>"3", :d=>"4"}}
t.except_nested!(:c)
# t => {:a=>"1", :b=>{:d=>"4"}}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With