2017-06-15 14 views
-1

私はキーでグループ化し、別のキーの値を合計する必要があるダイナモテーブルからのハッシュの配列を持っています。ハッシュの別のキーのキー、合計値に基づいた配列のRubyマージハッシュ

data = [ 
    { 'state' => 'Florida', 'minutes_of_sun' => 10, 'timestamp' => 1497531600, 'region' => 'Southeast' }, 
    { 'state' => 'Florida', 'minutes_of_sun' => 7, 'timestamp' => 1497531600, 'region' => 'Southeast' }, 
    { 'state' => 'Florida', 'minutes_of_sun' => 2, 'timestamp' => 1497531600, 'region' => 'Southeast' }, 
    { 'state' => 'Georgia', 'minutes_of_sun' => 15, 'timestamp' => 1497531600, 'region' => 'Southeast' }, 
    { 'state' => 'Georgia', 'minutes_of_sun' => 5, 'timestamp' => 1497531600, 'region' => 'Southeast' } 
] 

私が探していられる最終的な結果は次のとおりです:私の配列はようになります

data = [ 
    { 'state' => 'Florida', 'minutes_of_sun' => 19, 'region' => 'Southeast' }, 
    { 'state' => 'Georgia', 'minutes_of_sun' => 20, 'region' => 'Southeast' } 
] 

私は以下の書いたメソッドを介してこれを行うことができましたが、それは遅いですし、 clunky。これを行うにはもっと速く/少ないLoC方法があるのだろうかと疑問に思っていましたか?

def combine_data(data) 
    combined_data = [] 

    data.each do |row| 
    existing_data = combined_data.find { |key| key['state'] == row['state'] } 
    if existing_data.present? 
     existing_data['minutes_of_sun'] += row['minutes_of_sun'] 
    else 
     combined_data << row 
    end 
    end 

    combined_data 
end 
+0

'data.group_by {返すことに注意してください|時間| h ['state']} .values.map {| hs | hs.inject {| a、b | a.merge(b){| key、oldval、newval | oldval + newval}}} ' – falsetru

+0

' data.group_by {| h | h ['state']} .values.map {| hs | hs.inject {| a、b | a ['minutes_of_sun'] + = b ['minutes_of_sun']; (元の 'data'ハッシュが変更されても気にしない場合) – falsetru

+0

[同じ値を持つ場合、ハッシュの配列の合計値]の複製が可能です(https://stackoverflow.com/questions/43876712/)。この質問は複数回尋ねられています(最初に検索しましたか?)ただグーグルで検索すると数十の検索結果が表示されなくなりましたあまりにもハード – engineersmnky

答えて

1

あなたがキーの値を決定するためにブロックを採用してHash#updateの形(別名merge!)を使用することができますルビー2.4.0

data.group_by { |item| item['state'] }.values.map do |arr| 
    h = arr.first 
    h.delete('timestamp') 
    h.merge('minutes_of_sun' => arr.sum { |item| item['minutes_of_sun'] }) 
end 
=> [{"state"=>"Florida", "minutes_of_sun"=>19, "region"=>"Southeast"}, {"state"=>"Georgia", "minutes_of_sun"=>20, "region"=>"Southeast"}] 
0

からこの1

data.group_by { |item| item['state'] }.values.map do |arr| 
    h = arr.first 
    h.delete('timestamp') 
    h.merge('minutes_of_sun' => arr.inject { |acc, h| acc + h['minutes_of_sun'] }) 
end 
=> [{"state"=>"Florida", "minutes_of_sun"=>19, "region"=>"Southeast"}, {"state"=>"Georgia", "minutes_of_sun"=>20, "region"=>"Southeast"}] 

をお試しください両方のハッシュがマージされています。そのブロック内の3つのブロック変数の説明については、docを参照してください。

data = [ 
    { 'state'=>'Florida', 'sun_min'=>10, 'stamp'=>149, 'region'=>'SE' }, 
    { 'state'=>'Georgia', 'sun_min'=>15, 'stamp'=>149, 'region'=>'SE' }, 
    { 'state'=>'Georgia', 'sun_min'=> 5, 'stamp'=>149, 'region'=>'SE' } 
] 

data.each_with_object({}) do |g,h| 
    h.update(g['state']=>g.reject { |k,_| k=='stamp' }) do |_,o,n| 
    o.merge('sun_min'=>o['sun_min']+n['sun_min']) 
    end 
end.values 
    #=> [{"state"=>"Florida", "sun_min"=>10, "region"=>"SE"}, 
    # {"state"=>"Georgia", "sun_min"=>20, "region"=>"SE"}] 

.valuesせず、これは

#=> {"Florida"=>{"state"=>"Florida", "sun_min"=>10, "region"=>"SE"}, 
# "Georgia"=>{"state"=>"Georgia", "sun_min"=>20, "region"=>"SE"}} 
関連する問題