2016-03-31 3 views
0

私はこのようになりますアレー持っている:Rubyでこの配列を再構成するより良い方法はありますか?

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

をそして私は今年、作る、モデル、シリーズやスタイルの各組み合わせがハッシュに結合し、挿入された以下、この配列を変換したいですアレイに入れる。

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

私は実用的なソリューションを持っていますが、誰もが解決策よりエレガントなソリューションを作成する方法上の任意のアイデアを持っている場合、私は思ったんだけど。

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 

この優れたソリューション作るためにRubyの配列方法のいくつかを利用する方法はありますか?

編集:再帰を使用してほぼ完了しているソリューションです。

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

なぜ 'さ:uvc'は含まれ? – sawa

+0

'uvc'は、年、メイク、モデル、シリーズ、スタイルの組み合わせごとの固有の識別子です。残念ながら、これはこのサードパーティ製のAPIが返すcruddyデータ構造であり、なぜ私はそれを少し正規化しようとしています。 – doremi

答えて

1

これは、任意の追加のアキュムレータやコードの行数を縮小し、それが明確になり、一時的な変数なしであなたのソリューションを書き換えることが可能です。私のソリューションは、配列マップメソッドのみを使用して、目的の結果を返しますが、配列に深くラップします。すべての外部配列ラッパーは、Array flattenメソッド呼び出しで削除できます。 これはirbコンソールからの出力です。

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

あなたは、あるように、すべてのキーの値を渡しますが、このような_listなものを探して再帰的にinjectことがあります。

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) 
関連する問題