2010-12-06 21 views
0

Je dispose d'un tableau de hachages qui ressemble à ceci:somme de hash basée sur d'autres champs de hachage

[{:head_count=>150.5, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>201.0, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>103.5, :group=>"NW", :estimated_ship_date=>"201104", :yard=>"nyssa"}] 

Je cherche à créer un hachage de ces données qui ressemble à ceci:

{ 
    "wcc" => 
    { 
    "NW" => 
    { 
     "201105" => 351.5 # This being a sum 
    } 
    } 
    "nyssa" => 
    { 
    "NW" => 
    { 
     "201104" => 103.5 # This being a sum 
    } 
    } 
} 

Je ne suis pas sûr de ce que d'autres données que je peux fournir.

J'ai essayé une collecte, mais je n'ai pas pu déterminer par où commencer.

Merci

+0

La somme est de 351,5 (pas 251,5), non? – Nakilon

+0

haha ​​ouais, oups. –

+0

J'aimerais pouvoir répondre à toutes ces questions ... de bonnes réponses, certaines sont un peu difficiles à comprendre, mais je suis sûr qu'elles sont les solutions les plus avancées. –

Répondre

1

Je voudrais juste utiliser une simple boucle.

a = [{:head_count=>150.5, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>201.0, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>103.5, :group=>"NW", :estimated_ship_date=>"201104", :yard=>"nyssa"}] 

yards = {} 
a.each do |h| 
    yard = yards[h[:yard]] ||= {} 
    group = yard[h[:group]] ||= {} 
    group[h[:estimated_ship_date]] ||= 0.0 
    group[h[:estimated_ship_date]] += h[:head_count] 
end 

# yards => {"wcc"=>{"NW"=>{"201105"=>351.5}}, "nyssa"=>{"NW"=>{"201104"=>103.5}}} 
3

Une version légèrement différente en utilisant le proc par défaut de hashs à auto-vivifier les conteneurs:

a = [ 
    {:head_count=>150.5, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
    {:head_count=>201.0, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
    {:head_count=>103.5, :group=>"NW", :estimated_ship_date=>"201104", :yard=>"nyssa"} 
] 

yards = Hash.new{ |h,yard| 
    h[yard]=Hash.new{ |h,group| 
    h[group]=Hash.new{ |h,est_date| 
     h[est_date]=0 
    } 
    } 
} 
a.each do |h| 
    yards[h[:yard]][h[:group]][h[:estimated_ship_date]] += h[:head_count] 
end 

p yards 
#=> {"wcc"=>{"NW"=>{"201105"=>351.5}}, "nyssa"=>{"NW"=>{"201104"=>103.5}}} 
1
x = [ 
{:head_count=>100, :group=>"NE", :estimated_ship_date=>"201103", :yard=>"wcc"}, 
{:head_count=>200, :group=>"NW", :estimated_ship_date=>"201104", :yard=>"wcc"}, 
{:head_count=>300, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>400, :group=>"NW", :estimated_ship_date=>"201105", :yard=>"wcc"}, 
{:head_count=>500, :group=>"NW", :estimated_ship_date=>"201104", :yard=>"nyssa"}] 

p Hash[ x.group_by{ |i| i[:yard] }.map { |i,j| 
    [i, Hash[ j.group_by { |i| i[:group] }.map { |i,j| 
     [i, Hash[ j.group_by { |i| i[:estimated_ship_date] }.map{ |i,j| 
      [i, j.map{ |i| i[:head_count] }.inject(:+)] 
     } ] ] 
    } ] ] 
} ] 

{ 
    "wcc"=> 
    { 
     "NE"=> 
     { 
      "201103"=>100 
     }, 
     "NW"=> 
     { 
      "201104"=>200, 
      "201105"=>700 
     } 
    }, 
    "nyssa"=> 
    { 
     "NW"=> 
     { 
      "201104"=>500 
     } 
    } 
} 
1

Voilà ma solution.

yards = [] 
a.select{|x| yards << x[:yard]} 
sol = Hash.new{|k,v| k[v] = Hash.new{|k,v| k[v] = {} } } 
yards.uniq.map do |x| 
    a.select{|y| x == y[:yard]}.flatten.map do |z| 
    sol[x][z[:group]][z[:estimated_ship_date]] = 0.0 
    sol[x][z[:group]][z[:estimated_ship_date]] += z[:head_count] 
    end 
end 

Votre tableau initial est un. Et les solutions sont sol. J'espère que cela semble lisible