2016-03-31 24 views
0

Şöyle bir dizi var:Bu diziyi Ruby'de yeniden yapılandırmanın daha iyi bir yolu var mı?

{ 
    year_list: [{ 
     name: 2016, 
     make_list: [{ 
      name: 'Honda', 
      model_list: [{ 
       name: 'CRV', 
       series_list: [{ 
        name: 'Premium Plus', 
        style_list: [{ 
         name: '4D SUV', 
         uvc: '123abc' 
        }] 
       }] 
      }] 
     }] 
    }] 
} 

Ve ben bir karma birleştirilir yılın her kombinasyonu yapmak Aşağıda, model, seri ve stil için bu diziyi dönüştürmek istiyoruz ve takılı diziye

[{:year=> 2016, 
    :make=>"Honda", 
    :model=>"CRV", 
    :series=>"Premium Plus", 
    :style=>"4D SUV", 
    :uvc=>"123abc"}] 

Ben çalışan bir çözüm var, ama kimse çözüm daha zarif bir çözüm yapmak konusunda herhangi bir fikir olup olmadığını merak ediyorum.

list = [] 
year_list.each do |y_val| 
    vehicle_type = {} 
    vehicle_type[:year] = y_val['name'] 

    make_list = y_val['make_list'] 
    make_list.each do |k_val| 
    vehicle_type[:make] = k_val['name'] 

    model_list = k_val['model_list'] 
    model_list.each do |m_val| 
     vehicle_type[:model] = m_val['name'] 

     series_list = m_val['series_list'] 
     series_list.each do |s_val| 
     vehicle_type[:series] = s_val['name'] 

     style_list = s_val['style_list'] 
     style_list.each do |st_val| 
      vehicle_type[:style] = st_val['name'] 
      vehicle_type[:uvc] = st_val['uvc'] 
      list << vehicle_type 
     end 
     end 
    end 
    end 
end 

Bunu daha iyi bir çözüm yapmak için Ruby'nin dizi yöntemlerinden bazılarını kullanmanın bir yolu var mı?

Düzenleme: İşte hemen hemen özyinelemeyi kullanarak çalışan bir çözüm.

VEHICLES = [] 
ELEMENTS = [:year, :make, :model, :series, :style] 

def walk_tree(arr, vehicle={}) 
    arr[0..1].each do |a| 
    name = a['name'] 

    if a.key?('uvc') 
     vehicle[:uvc] = a['uvc'] 
     VEHICLES << vehicle 
     vehicle = {} 
     next 
    end 

    ELEMENTS.each do |s| 
     key = s.to_s + '_list' 
     if a.key?(key) 
     vehicle[s] = name 
     walk_tree(a[key], vehicle) 
     end 
    end 

    end 
end 

walk_tree(year_list) 
pp LIST 
+0

edilir: dahil uvc'? – sawa

+0

'uvc' her yıl, marka, model, seri, stil kombinasyonu için benzersiz bir tanımlayıcıdır. Ne yazık ki, bu 3. parti API'nin döndürdüğü kaba bir veri yapısı ve neden normalleştirmeye çalışıyorum. – doremi

cevap

1

Bu kod satır sayısını küçültmek ve buna açıklık getirecek herhangi bir ek aküler veya geçici değişkenler olmadan çözüm yeniden yazmak mümkündür. Çözümüm, istenen sonucu döndürecek ancak dizilere derinlemesine sarılacak olan Array haritası yöntemini kullanır. Tüm dış dizi sarmalayıcıları Array flatten yöntem çağrısı ile kaldırılabilir. İşte irb konsolundan çıktı.

super_hash[:year_list].map do |year| 
    year[:make_list].map do |make| 
    make[:model_list].map do |model| 
     model[:series_list].map do |series| 
     series[:style_list].map do |style| 
      { 
      year: year[:name], 
      make: make[:name], 
      model: model[:name], 
      series: series[:name], 
      style: style[:name], 
      uvc: style[:uvc] 
      } 
     end 
     end 
    end 
    end 
end 
#=> [[[[[{:year=>2016, :make=>"Honda", :model=>"CRV", :series=>"Premium Plus", :style=>"4D SUV", :uvc=>"123abc"}]]]]] 
[[[[[{:year=>2016, :make=>"Honda", :model=>"CRV", :series=>"Premium Plus", :style=>"4D SUV", :uvc=>"123abc"}]]]]].flatten 
#=> [{:year=>2016, :make=>"Honda", :model=>"CRV", :series=>"Premium Plus", :style=>"4D SUV", :uvc=>"123abc"}] 
0

Sen yinelemeli inject, olduğu gibi tüm anahtar değerlerini geçirerek, ama böyle _list olanlar için seyir olabilir: Neden `

l = ->(h,(k,v)){ 
    if k =~ /(\w+)_list$/ 
    h[$1] = v.first[:name] 
    return v.first.inject(h, &l) 
    end 
    h[k] = v 
    h 
} 

p year_list.inject({}, &l) 
İlgili konular