通过Ruby中的嵌套JSON进行迭代

时间:2014-11-21 03:38:06

标签: ruby-on-rails ruby json

第一次在这里发帖。 无法进入JSON,我可以使用一些活动的。

我需要的数据是在这个级别:

restaurant["menu"][0]["children"][0]["name"]

restaurant["menu"][0]["children"][0]["id"]

我想要一个基于“名字”的“id”数组。

这是我正在使用的方法:

def find_burgers(rest)

    array = []

    rest["menu"].each do |section| 
    section["children"].each do |innersection| 
    innersection["name"].downcase.split.include?("burger")
    array.push(innersection["id"]) 
    end
  end   
  return array
end

你可以想象,我正在找回每个“id”的数组,而不仅仅是汉堡的“id”。我尝试了很多.map和.keep_if的组合。

感谢阅读。

编辑:这是一个菜单项:

{
    "children" => [
    [ 0] {
        "availability" => [
            [0] 0
        ],
            "children" => [
            [0] {
                             "children" => [
                    [0] {
                        "availability" => [
                            [0] 0
                        ],
                             "descrip" => "",
                                  "id" => "50559491",
                        "is_orderable" => "1",
                                "name" => "Single",
                               "price" => "0.00"
                    },
                    [1] {
                        "availability" => [
                            [0] 0
                        ],
                             "descrip" => "",
                                  "id" => "50559492",
                        "is_orderable" => "1",
                                "name" => "Double",
                               "price" => "2.25"
                    }
                ],
                              "descrip" => "What Size Would You Like?",
                    "free_child_select" => "0",
                                   "id" => "50559490",
                         "is_orderable" => "0",
                     "max_child_select" => "1",
                "max_free_child_select" => "0",
                     "min_child_select" => "1",
                                 "name" => "Milk Burger Size"
            },
            [1] {
                             "children" => [
                    [0] {
                        "availability" => [
                            [0] 0
                        ],
                             "descrip" => "",
                                  "id" => "50559494",
                        "is_orderable" => "1",
                                "name" => "Bacon",
                               "price" => "2.00"
                    }
                ],
                              "descrip" => "Add",
                    "free_child_select" => "0",
                                   "id" => "50559493",
                         "is_orderable" => "0",
                     "max_child_select" => "1",
                "max_free_child_select" => "0",
                     "min_child_select" => "0",
                                 "name" => "Burgr Ad Bacon Optn"
            }
        ],
             "descrip" => "American cheese, lettuce, tomato and Milk Sauce",
                  "id" => "50559489",
        "is_orderable" => "1",
                "name" => "Milk Burger",
               "price" => "4.25"
    },

3 个答案:

答案 0 :(得分:3)

通常,您可以像这样迭代嵌套哈希:

def iterate(h)
  h.each do |k, v| 
    if v.is_a?(Hash) || v.is_a?(Array)
      iterate(v)
    else
      puts("k is #{k}, value is #{v}")
    end
  end
end

但是既然你拥有具体的,硬编码的名字children, name等,那么这样做的唯一方法就是你做这件事的方式。

答案 1 :(得分:2)

在JSON中迭代Hashes或Arrays的更准确的答案

j = {'key$1' => 'asdada',
     'key$2' => ['key$3' => 2,
                 'key$4' => 's',
                 'key$6' => ['key$7' => 'man',
                             'key$8' => 'super']
                 ],
     'key5' => 5 }

def iterate(i)
  if i.is_a?(Hash)
    i.each do |k, v|
      if v.is_a?(Hash) || v.is_a?(Array)
        puts("k is #{k}, value is #{v}")
        iterate(v)
      else
        puts("k is #{k}, value is #{v}")
      end
    end
  end
  if i.is_a?(Array)
    i.each do |v|
      iterate(v)
    end
  end
end

iterate(j)

答案 2 :(得分:1)

您正在执行测试以查看该名称是否包含“汉堡”,但您没有对测试结果做任何事情。试试这个:

def find_burgers(rest)

  array = []

  rest["menu"].each do |section| 
    section["children"].each do |innersection| 
      array.push(innersection["id"]) if innersection["name"].downcase.split.include?("burger")
    end
  end   
  return array
end

另外,考虑使用正则表达式而不是`downcase.split.include?'像这样:

def find_burgers(rest)

  array = []

  rest["menu"].each do |section| 
    section["children"].each do |innersection| 
      array.push(innersection["id"]) if innersection["name"] =~ /\bburger\b/i
    end
  end   
  return array
end

如果名称包含由分词符号(\ b)忽略大小写(/ i)的字符串“burger”,则正则表达式返回true。

最后(我认为)你可以使用更具功能性的方法:

def find_burgers(rest)
  rest["menu"].map do |section| 
    section["children"].select do |innersection| 
      innersection["name"] =~ /\bburger\b/i
    end
  end.flatten.map {|item| item["id"] }
end

select仅返回与正则表达式匹配的项,第一个map返回每个section的匹配内置项数组,flatten将数组数组转换为简单的数组,最终的地图只从每个内部选择id

我想我走得太远了。