1

特定の重複キー値を含むハッシュをマージするハッシュの配列があります。

combined_keywords = new_array_of_hashes.each_with_object(Hash.new(0)){|oh, newh|
        newh[oh[:keyword]] += oh[:total_value].to_f
    }

これにより、次のようなハッシュの配列が作成されます。

 { :ACTUAL_KEYWORD => ACTUAL_TOTAL_VALUE }

私は ruby​​ を初めて使用し、この背後にある魔法をよく理解していません。統合する追加のキーと値があり、今は迷っています。問題の根本は、次の行で統合がどのように発生しているのか理解できないことです。newh[oh[:keyword]] += oh[:total_value].to_f

私は運がないのでこれを試しました:

combined_keywords = new_array_of_hashes.each_with_object(Hash.new(0)){|oh, newh|
            newh[oh[:keyword]] += oh[:total_value].to_f
            newh[oh[:keyword]] += oh[:revenue_per_transaction].to_f
        }

私は本当に、それぞれが次のような統合されたハッシュの配列を必要としています:

{ :keyword => "ACTUAL_KEYWORD", :total_value => ACTUAL_TOTAL_VALUE, :revenue_per_transaction => ACTUAL_REVENUE }

編集:

入力

new_array_of_hashes = [
  { keyword: 'foo', total_value: 1, revenue_per_transaction: 5 },
  { keyword: 'bar', total_value: 2, revenue_per_transaction: 4 },
  { keyword: 'bar', total_value: 4, revenue_per_transaction: 4 },
  { keyword: 'foo', total_value: 3, revenue_per_transaction: 5 },
]

望ましい出力

combined_keywords = [
  { keyword: 'foo', total_value: 4, revenue_per_transaction: 10 },
  { keyword: 'bar', total_value: 6, revenue_per_transaction: 8 },
]
4

2 に答える 2

3

あなたが持っているとしましょう:

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です。

于 2013-05-10T00:57:17.037 に答える