Search code examples
rubyrecursionruby-hash

Remove hash from an array of hash that contains specific keys


I have this hash :

{ "car": [
  { "key": 'removeMe1', "name": 'ok' },
  { "key": 'dontRemoveMe1', "surname": 'ok' },
  { "key": 'dontRemoveMe2',
    "array": [
      { "trucks": [
        { "key": 'removeMe2', "name": 'my_profile_name' }
      ] },
      { "trucks": [
        { "key": 'dontRemoveMe3', "name": '34' },
        { "key": 'removeMe3', "surname": '5324' }
      ]}
  ] }
]}

And I would like to remove hash that contains removeMe*

{ "car": [
  { "key": 'dontRemoveMe1', "surname": 'ok' },
  { "key": 'dontRemoveMe2',
    "array": [
      { "trucks": [
        { "key": 'dontRemoveMe3', "name": '34' }
      ] }
  ] }
]}

I succeed at the first level if I do

my_hash.delete_if { |h| ['removeMe1'].exclude?(h['key']) }

But I don't know how to do it for nested levels.


Solution

  • def delete_by_key(data)
      data.each do |k, v|
        if Array === v
          v.each{ |i| delete_by_key(i) }
          v.delete_if { |i| i[:key] && i[:key]["removeMe"] or i.empty? }
          data.delete(k) if v.empty?
        end
      end
    end
    

    The result is following

    data = { 
      "car": [
        { "key": 'removeMe1', "name": 'ok' },
        { "key": 'dontRemoveMe1', "surname": 'ok' },
        { "key": 'dontRemoveMe2',
          "array": [
            { "trucks": [
              { "key": 'removeMe2', "name": 'my_profile_name' }
            ] },
            { "trucks": [
              { "key": 'dontRemoveMe3', "name": '34' },
              { "key": 'removeMe3', "surname": '5324' }
            ]}
        ] 
      }
    ]}
    
    delete_by_key(data)
    #=> {:car=>[{:key=>"dontRemoveMe1", :surname=>"ok"}, {:key=>"dontRemoveMe2", :array=>[{:trucks=>[{:key=>"dontRemoveMe3", :name=>"34"}]}]}]}