あなたが持っているとしましょう:
new_array_of_hashes = [
{ keyword: 'foo', total_value: 1 },
{ keyword: 'bar', total_value: 2 },
{ keyword: 'bar', total_value: 4 },
{ keyword: 'foo', total_value: 3 },
]
次に、コードをステップ実行します。
combined_keywords = new_array_of_hashes.each_with_object(Hash.new(0)){|oh, newh|
newh[oh[:keyword]] += oh[:total_value].to_f
}
これは、配列内の各ハッシュをループします。0
また、存在しないキーにアクセスした場合に返される新しいハッシュをセットアップします。
# Pass 1
oh = { keyword: 'foo', total_value: 1 }
newh = {}
newh[ oh[:keyword] ] #=> newh['foo'] This key doesn't exist and returns 0
oh[:total_value].to_f #=> 1.to_f => 1.0
newh[oh[:keyword]] += oh[:total_value].to_f
#=> newh['foo'] = newh['foo'] + oh[:total_value].to_f
#=> newh['foo'] = 0 + 1.0
# Pass 2
oh = { keyword: 'bar', total_value: 2 }
newh = { 'foo' => 1.0 }
newh[ oh[:keyword] ] #=> newh['bar'] This key doesn't exist and returns 0
oh[:total_value].to_f #=> 2.to_f => 2.0
newh[oh[:keyword]] += oh[:total_value].to_f
#=> newh['bar'] = newh['bar'] + oh[:total_value].to_f
#=> newh['bar'] = 0 + 2.0
次の 2 つの反復のキーがあるので、通常どおりにアクセスします。
# Pass 3
oh = { keyword: 'bar', total_value: 4 }
newh = { 'foo' => 1.0, 'bar' => 2.0 }
newh[ oh[:keyword] ] #=> newh['bar'] This key now exists and returns 2.0
oh[:total_value].to_f #=> 4.to_f => 4.0
newh[oh[:keyword]] += oh[:total_value].to_f
#=> newh['bar'] = newh['bar'] + oh[:total_value].to_f
#=> newh['bar'] = 2.0 + 4.0
# Pass 4
oh = { keyword: 'foo', total_value: 3 }
newh = { 'foo' => 1.0, 'bar' => 6.0 }
newh[ oh[:keyword] ] #=> newh['foo'] This key now exists and returns 1.0
oh[:total_value].to_f #=> 3.to_f => 3.0
newh[oh[:keyword]] += oh[:total_value].to_f
#=> newh['foo'] = newh['foo'] + oh[:total_value].to_f
#=> newh['foo'] = 1.0 + 3.0
ブロックが戻ると、戻りnewh
ます。これがどのように機能するかeach_with_object
です。
ご覧のとおり、返されるのは次の形式のハッシュです。
{ 'foo' => 4.0, 'bar' => 6.0 }
したがって、これは、新しいキーが格納された:keyword
オブジェクトであり、値が合計である結合配列のみです。
新しいハッシュ形式に基づく
{
keyword: "ACTUAL_KEYWORD",
total_value: ACTUAL_TOTAL_VALUE,
revenue_per_transaction: ACTUAL_REVENUE
}
この形式はあまり意味がありません。ハッシュにはキーと値のペアしかないためです。サブハッシュのハッシュを取得するか、ループを 2 回実行する必要がある場合があります。一:total_value
度だけ、一度だけ:revenue_per_transaction
。最終的なオブジェクトをどうしたいかによって異なります。
編集:
新しい予想される入力と出力に基づいて、次を使用できます。
sum_keys = [:total_value, :revenue_per_transaction]
new_array_of_hashes.group_by{ |h| h[:keyword] }
.map{ |keyword, related|
tmp = {keyword: keyword}
tmp.merge! Hash[sum_keys.zip Array.new(sum_keys.size, 0)]
related.reduce(tmp){ |summed, h|
sum_keys.each{ |key| summed[key] += h[key] }
summed
}
}
#=> [
# { keyword: 'foo', total_value: 4, revenue_per_transaction: 10 },
# { keyword: 'bar', total_value: 6, revenue_per_transaction: 8 },
#]
少し面倒です。map
おそらく、呼び出しが行っていることを独自のヘルパー メソッドにリファクタリングするでしょう。に開始値を指定しreduce
ている理由は、それ以外の場合は元のハッシュが から変更されるためnew_array_of_hashes
です。