Суммарный массив хэшей, основанный на других полях в хэше - PullRequest
0 голосов
/ 06 декабря 2010

У меня есть массив хэшей, который выглядит так:

[{: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"}]

Я хочу создать хеш из этих данных, который выглядит следующим образом:

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

Я не уверен, какие еще данные я могу предоставить.

Я попытался собрать, но не мог понять, с чего начать.

Спасибо

Ответы [ 4 ]

3 голосов
/ 06 декабря 2010

Немного другая версия, использующая процедуру по умолчанию Хэшей для автоматического оживления контейнеров:

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 голос
/ 06 декабря 2010

Вот мое решение.

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

Ваш начальный массив a.И решения соль.Я надеюсь, что это выглядит читабельным

1 голос
/ 06 декабря 2010
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 голос
/ 06 декабря 2010

Я бы просто использовал простой цикл.

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}}}
...