2017-03-22 7 views
0

私はJSで解決した問題を解決しましたが、Ruby(RoR)で行う必要があります。ここで問題と解決へのリンクは次のとおりです。Find average value for array of hashes using multiple group by複数のキーでハッシュをグループ化し、Rubyの平均値を求める配列

だから私は、キーによってグループ化される必要がハッシュの配列(最初subject_idelement_id)を持っているし、それらの平均値を見つけます。配列内のハッシュ数は固定されていません。以下は

は入力配列です:

a=[ 
{:subject_id=>1, :element_id=>2, :value=>55}, 
{:subject_id=>1, :element_id=>4, :value=>33}, 
{:subject_id=>1, :element_id=>2, :value=>33}, 
{:subject_id=>1, :element_id=>4, :value=>1}, 
{:subject_id=>1, :element_id=>2, :value=>7}, 
{:subject_id=>1, :element_id=>4, :value=>4}, 
{:subject_id=>2, :element_id=>2, :value=>3}, 
{:subject_id=>2, :element_id=>2, :value=>5}, 
{:subject_id=>2, :element_id=>4, :value=>9} 
] 

結果:

b=[ 
{:subject_id=>1, :element_id=>2, :value=>95}, 
{:subject_id=>1, :element_id=>4, :value=>38}, 
{:subject_id=>2, :element_id=>2, :value=>8}, 
{:subject_id=>2, :element_id=>4, :value=>9} 
] 

答えて

0

質問に示す結果は、それは合計平均だではないので、結果が異なることになります。

def groupByAndAverage(a) 
    b = [] 

    a.each_with_index do |element, key| 
     index = b.index do |x| 
     x != element && 
      x[:subject_id] == element[:subject_id] && 
      x[:element_id] == element[:element_id] 
     end 
     if index 
     b[index][:value] += element[:value] 
     b[index][:amount] += 1 
     else 
     b.push a[key].merge(amount: 1) 
     end 

     true 
    end 
    b.map do |element| 
     element[:value] = element[:value]/element[:amount] 
     element.delete(:amount) 
     element 
    end 
    b 
    end 

そしてこれからの結果is:

[{:subject_id=>1, :element_id=>2, :value=>31}, 
    {:subject_id=>1, :element_id=>4, :value=>12}, 
    {:subject_id=>2, :element_id=>2, :value=>4}, 
    {:subject_id=>2, :element_id=>4, :value=>9}] 
+0

はい、ありがとう、間違いでした – user7754069

0

私はカウントハッシュキー:valueの小計を取得し、その後、アレイの必要な構築するために使用されことを示唆していますそのハッシュのハッシュの数。これは、Hash#newの形式を使用します。この形式では、ハッシュのデフォルト値を引数にとります。つまり、ハッシュhにキーkがない場合は、h[k]がデフォルト値を返します。

コンピューティングが

a.each_with_object(Hash.new(0)) {|g,h| h[[g[:subject_id], g[:element_id]]] += g[:value]}. 
    map {|(sub, el), tot| { subject_id: sub, element_id: el, value: tot}} 
    #=> [{:subject_id=>1, :element_id=>2, :value=>95}, 
    # {:subject_id=>1, :element_id=>4, :value=>38}, 
    # {:subject_id=>2, :element_id=>2, :value=>8}, 
    # {:subject_id=>2, :element_id=>4, :value=>9}] 

ルビーを合計hキー[g[:subject_id], g[:element_id]]を持っていない場合は、最初のステップとして、

h[[g[:subject_id], g[:element_id]]] = h[[g[:subject_id], g[:element_id]]] + g[:value] 

に変更する表現

h[[g[:subject_id], g[:element_id]]] += g[:value] 

をアンパック、一致の右側にあるは、デフォルト値の0を返します。

a.each_with_object(Hash.new(0)) {|g,h| h[[g[:subject_id], g[:element_id]]] += g[:value]} 
    #=> {[1, 2]=>95, [1, 4]=>38, [2, 2]=>8, [2, 4]=>9} 

のみの小さな変更が平均値を計算するために必要とされる平均値

を計算することを

注意。

a.each_with_object({}) do |g,h| 
    pair = [g[:element_id], g[:subject_id]] 
    h[pair] = {tot: 0, count: 0} unless h.key?(pair) 
    h[pair] = {tot: h[pair][:tot] + g[:value], count: h[pair][:count]+1} 
end.map {|(sub, el),h| {subject_id: sub, element_id: el, 
         average: (h[:tot].to_f/h[:count]).round(1)}} 
    #=> [{:subject_id=>2, :element_id=>1, :average=>31.7}, 
    # {:subject_id=>4, :element_id=>1, :average=>12.7}, 
    # {:subject_id=>2, :element_id=>2, :average=>4.0}, 
    # {:subject_id=>4, :element_id=>2, :average=>9.0}] 

a.each_with_object({}) do |g,h| 
    pair = [g[:element_id], g[:subject_id]] 
    h[pair] = {tot: 0, count: 0} unless h.key?(pair) 
    h[pair] = {tot: h[pair][:tot] + g[:value], count: h[pair][:count]+1} 
end 
    #=> {[2, 1]=>{:tot=>95, :count=>3}, [4, 1]=>{:tot=>38, :count=>3}, 
    # [2, 2]=>{:tot=> 8, :count=>2}, [4, 2]=>{:tot=> 9, :count=>1}} 
+0

ありがとう、私は間違いを犯した私が平均の代わりに結果として合計を示したところで十分です。 – user7754069

+0

私は平均の計算を追加しました。 –

関連する問題