[英]Iterating through nested JSON in Ruby
第一次在這里發布。 進入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"
},
通常,您可以像下面這樣遍歷嵌套的哈希:
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
等,看來唯一的方法就是您執行此操作。
在JSON中的哈希或數組上迭代的更准確的答案
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)
您正在執行一項測試,以查看名稱中是否包含“ burger”,但您並未對測試結果做任何事情。 嘗試以下方法:
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
如果名稱包含字符串“ burger”,且字符串以斷字(\\ b)包圍且忽略大小寫(/ i),則正則表達式返回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
傳回一個匹配的內部section
的數組,flatten將數組的數組變成一個簡單的數組,最后一個映射僅從每個內部部分中提取id
。
我想我走得太遠了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.