以递归方式在ruby中搜索哈希并返回一个项目数组

时间:2012-02-02 19:14:21

标签: ruby-on-rails ruby

我有一个哈希,我从使用JSON.parse。那时我正在插入db。数据结构使用act作为树,所以我可以有这样的哈希:

category_attributes
  name: "Gardening"
  items_attributes:
    item 1: "backhoe"
    item 2: "whellbarrel"
  children_attributes
    name: "seeds"
    items_attributes
      item 3: "various flower seeds"
      item 4: "various tree seeds"
    children_attributes
      name: "agricultural seeds"
      items_attributes
        item 5: "corn"
        item 6: "wheat"

对于这个哈希,我想返回所有items_attributes的数组。我看到了这个问题Traversing a Hash Recursively in Ruby,但似乎有所不同。有没有办法递归搜索哈希并返回所有这些元素?理想情况下,空的items_attributes应该只返回nil。

THX

2 个答案:

答案 0 :(得分:3)

试试这个:

def extract_list(hash, collect = false)
  hash.map do |k, v|
    v.is_a?(Hash) ? extract_list(v, (k == "items_attributes")) : 
       (collect ? v : nil)
  end.compact.flatten
end

现在让我们测试一下这个功能:

>> input = {    
  'category_attributes' => {
    'name' => "Gardening",
    'items_attributes' => {
      'item 1' =>  "backhoe",
      'item 2' =>  "whellbarrel",
      'children_attributes' => {
        'name' =>  "seeds",
        'items_attributes' => {
          'item 3' =>  "various flower seeds",
          'item 4' =>  "various tree seeds"
        },      
        'children_attributes' => {
          'name' =>  "agricultural seeds",
          'items_attributes' => {
            'item 5' => "corn",
            'item 6' => "wheat"
          }
        }
      }
    }
  }
}

>> extract_list(input)    
=> ["various flower seeds", "various tree seeds", "wheat", "corn", 
     "backhoe", "whellbarrel"]

答案 1 :(得分:2)

您可以这样做:

def collect_item_attributes h
  result = {}
  h.each do |k, v|
    if k == 'items_attributes'
      h[k].each {|k, v| result[k] = v } # <= tweak here    
    elsif v.is_a? Hash
      collect_item_attributes(h[k]).each do |k, v|
        result[k] = v
      end
    end
  end
  result
end

puts collect_item_attributes(h)
# => {"item 1"=>"backhoe", 
# "item 2"=>"whellbarrel", 
# "item 3"=>"various flower seeds", 
# "item 4"=>"various tree seeds", 
# "item 5"=>"corn", 
# "item 6"=>"wheat"}