从包含特定键的散列数组中删除散列

Remove hash from an array of hash that contains specific keys

我有这个哈希:

{ "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' }
      ]}
  ] }
]}

我想删除包含 removeMe*

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

如果我这样做,我在第一级就成功了

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

但是我不知道如何为嵌套关卡做。

您可以使用以下解决方案:

def remove_me!(obj)
  case obj
  when Hash
    obj.each_value { |e| remove_me!(e) }
  when Array
    obj.reject! do |e| 
      e.is_a?(Hash) && e.values.any? do |v| 
        v.is_a?(String) && v.start_with?('removeMe') 
      end
    end

    obj.each { |e| remove_me!(e) }
  end
end
remove_me!(hash)
#=> {:car=>[{:key=>"dontRemoveMe1", :surname=>"ok"},
#           {:key=>"dontRemoveMe2", :array=>[{:trucks=>[]}, {:trucks=>[{:key=>"dontRemoveMe3", :name=>"34"}]}]}]}

但请注意,此方法会改变原始对象。您可以使用 dup 创建一个新的。

问题只是关于哈希,但您也可以添加检查空数组并删除它们的部分。

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

结果如下

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"}]}]}]}