2015-08-18 4 views
2

У меня есть следующие JSON,Рубин строительство массив

{ 
    "items": [ 
     { 
      "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 
     } 
    ] 
} 

Как я перебирать это и создать массив «значений». Я хочу что-то вроде [151,13 см, 170,39 сантиметра, ....]. Пожалуйста, покажите в этом какое-то направление. Благодарю.

Примечание: Я должен сделать это в Haml.

+2

Вы могли бы сделать это: 'json.scan (/ \ "дисплей \":. \" (\ D + \ \ d +)/сантиметровый). Flatten.map (&: to_f) # => [151.13, 170.39] '. –

+1

Знаете ли вы структуру (т. е. вложенные ключи и т. д.) или просто хотите выкопать вложенные хэши и массивы, пока не найдете строку, которая выглядит что вы хотите? –

+0

Я предлагаю вам приложить строку JSON одинарными кавычками, чтобы она была одной. –

ответ

1

Предполагая, что вы знаете структуру основного хэша, вы можете сделать это:

Код

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] 

хотя я сомнение в том, что это будет значительно более эффективно.

+0

Да, у меня уже есть «item_group» в объекте. Поэтому я хочу перебрать его и добавить все «значения» в массив. – sp1117

+0

Вместо трех циклов можно сказать g ['item_group'] ['section'] ['values']? – sp1117

+0

И проблема в том, что я использую это в Haml – sp1117

1

Я знаю, что есть несколько способов сделать это. Но если у вас действительно много сложных запросов JSON, вы можете попробовать ruby-jq gem. Это очень быстро, так как он использует Linux трубы

require 'jq' 
require 'jq/extend' 
json_content =   { 
     "items": [ 
      { 
       "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 
      } 
     ] 
    } 


jq_filter = ' .items | .[].item_group |.[].section| . [ ] .values | . [ ] .display' 

final_array = json_content.jq(jq_filter) 

    # => final_array = ["151.13 centimeter", "170.39 centimeter"] 
+0

Это интересно, @Amit. Обратите внимание, что вы можете написать 'json_content.jq (jq_filter) .map (&: to_f) # => [151.13, 170.39]', так как «151.13 у моей собаки есть блохи» .to_f # => 151.13'. –

Смежные вопросы