Предполагая, что вы знаете структуру основного хэша, вы можете сделать это:
Код
require 'json'
JSON.parse(json_str)['items'].each_with_object([]) do |g,arr|
g['item_group'].each do |gg|
gg['section'].each do |ggg|
ggg['values'].each { |gggg|arr << gggg['display'][/\d+\.\d+/].to_f }
end
end
end
#=> [151.13, 170.39]
Объяснение
шаги заключаются в следующем:
a = JSON.parse(json_str)
b = a['items']
enum = b.each_with_object([])
#=> #<Enumerator: [{"name"=>"table",..."total"=>1}]:each_with_object([])>
Мы можем увидеть элементы счетчику путем преобразования его в массив:
enum.to_a
#=> [[{"name"=>"table", "item_group"=>[{"code"=>"code1",
# "section"=>[{"unit"=>"centimeter",
# "values"=>[{"display"=>"151.13 centimeter"}]},
# { "unit"=>"centimeter (qualifier value)",
# "values"=>[{"display"=>"170.39 centimeter"}]}], "total"=>2}],
# "more_results"=>false,
# "total"=>1},
# []]]
Обратите внимание, что этот массив имеет один элемент, два-элемент массив а, содержащий хеш и пустой массив.
Первый элемент enum
передается к блоку и назначен блок переменных, используя параллельное назначение:
g, arr = enum.next
#=> {"name"=>"table",
# "item_group"=>[
# {"code"=>"code1",
# "section"=>[
# {"unit"=>"centimeter",
# "values"=>[
# {"display"=>"151.13 centimeter"}
# ]
# },
# {"unit"=>"centimeter (qualifier value)",
# "values"=>[
# {"display"=>"170.39 centimeter"}
# ]
# }
# ],
# "total"=>2}],
# "more_results"=>false,
# "total"=>1}
arr #=> []
c = g['item_group']
#=> [{"code"=>"code1",
# "section"=>[
# {"unit"=>"centimeter",
# "values"=>[
# {"display"=>"151.13 centimeter"}
# ]
# },
# {"unit"=>"centimeter (qualifier value)",
# "values"=>[
# {"display"=>"170.39 centimeter"}
# ]
# }
# ],
# "total"=>2}]
Примечание c
имеет вид [hash]
.
Первый элемент (и только) из c
передается его блоку и назначен его переменной блока:
gg = c.first
d = gg['section']
#=> [{"unit"=>"centimeter",
"values"=>[
{"display"=>"151.13 centimeter"}
]
},
{"unit"=>"centimeter (qualifier value)",
"values"=>[
{"display"=>"170.39 centimeter"}
]
}
]
ggg = d.first
#=> {"unit"=>"centimeter",
# "values"=>[
# {"display"=>"151.13 centimeter"}
# ]
# }
e = ggg['values']
#=> [{"display"=>"151.13 centimeter"}]
gggg = e.first
#=> {"display"=>"151.13 centimeter"}
f = gggg['display']
#=> "151.13 centimeter"
g = f[/\d+\.\d+/]
#=> "151.13"
i = g.to_f
#=> 151.13
arr << i
#=> [151.13]
arr
#=> [151.13]
Остальные расчеты аналогичны.
Альтернативное выражение
Если, как в примере, массивы JSON.parse(json_str)['items']
, g['item_group']
и ggg['values']
каждый из которых содержит один элемент (хэш), вы могли бы вместо того, чтобы написать:
JSON.parse(json_str)['items'].first['item_group'].first['section'].
each_with_object([]) do |g, arr|
arr << g['values'].first['display'][/\d+\.\d+/].to_f
end
#=> [151.13, 170.39]
хотя я сомнение в том, что это будет значительно более эффективно.
Вы могли бы сделать это: 'json.scan (/ \ "дисплей \":. \" (\ D + \ \ d +)/сантиметровый). Flatten.map (&: to_f) # => [151.13, 170.39] '. –
Знаете ли вы структуру (т. е. вложенные ключи и т. д.) или просто хотите выкопать вложенные хэши и массивы, пока не найдете строку, которая выглядит что вы хотите? –
Я предлагаю вам приложить строку JSON одинарными кавычками, чтобы она была одной. –