删除包含特定键=>的哈希值哈希递归数组中的值

时间:2016-03-23 16:05:00

标签: ruby algorithm recursion hash

我有以下数组(没有深度限制):

 arr = [
   {
     name: "foo",
     age: 12,
     children: [{
         name: "zoo",
         age: 44
       },
       {
         name: "taz",
         age: 17,
         children: [{
             name: 'tof',
             age: 23
           },
           {
             name: 'tok',
             age: 42
           }
         ]
       }
     ]
   },
   {
     name: "bar",
     age: 54
   }
 ]

我想删除包含age > 40的每个哈希,最后一个数组将是:

arr = [
       {
         name: "foo",
         age: 12,
         children: [{
             name: "taz",
             age: 17,
             children: [{
                 name: 'tof',
                 age: 23
               }
             ]
           }
         ]
       }
     ]

你知道我应该如何编写这个函数吗?

3 个答案:

答案 0 :(得分:3)

def deep_reject!(array, &block)
  return if array.nil?
  array.tap{|a| a.reject! &block}.each do |h| 
    deep_reject!(h[:children], &block)
    h.delete(:children) if h[:children].nil? or h[:children].empty?
  end
end

array = [
  {
    name: "foo",
    age: 12,
    children: [
      {
        name: "zoo",
        age: 44
      },
      {
        name: "taz",
        age: 17,
        children: [
          {
            name: 'tof',
            age: 44
          },
          {
            name: 'tok',
            age: 67
          }
        ]
      }
    ]
  },
  {
    name: "bar",
    age: 54
  }
]

deep_reject!(array) {|hash| hash[:age] > 40}

答案 1 :(得分:1)

也许是这样的。

INPUT:

array = [
  {
    name: "foo",
    age: 12,
    children: [
      {
        name: "zoo",
        age: 44
      },
      {
        name: "taz",
        age: 17,
        children: [
          {
            name: 'tof',
            age: 23
          },
          {
            name: 'tok',
            age: 42
          }
        ]
      }
    ]
  },
  {
    name: "bar",
    age: 54
  }
]

代码:

def remove_from_children(array)
  a = []
  array.each{|h|
    if h[:children] && !h[:children].empty?
      h[:children] = remove_from_children(h[:children])
    end
    a << h if h[:age] < 40
  }
  a
end

remove_from_children(array)

输出

[
  {
    :name => "foo",
    :age => 12,
    :children => [
      {
        :name => "taz",
        :age => 17,
        :children => [
          {
            :name => "tof",
            :age => 23
          }
        ]
      }
    ]
  }
]

答案 2 :(得分:0)

以下内容不会改变arr

def just_youngsters(arr, cutoff_age)
  arr.each_with_object([]) do |h,a|
    next if h[:age] > cutoff_age
    g = h.dup
    if g.key?(:children) 
      (g[:children] = just_youngsters(g[:children], cutoff_age))
      g.delete_if { |k,v| k==:children && v.empty? }
    end
    a << g
  end
end

just_youngsters(arr, 40)
  #=> [
  #    { 
  #      :name=>"foo",
  #      :age=>12,
  #      :children=>[
  #                  { 
  #                    :name=>"taz",
  #                    :age=>17
  #                  }
  #                 ]
  #    }
  #   ]