2012-04-26 2 views
0

Ruby On Rails 3.2.2, Ruby 1.9.3Рубин массив group_by вложенной хэш суммы полей

У меня есть данные массива из Siz.requirements.all (модель) модели поля (СИЗ, heigth, wigth, кол-)

[{:siz=>10, :heigth = 30, :wigth = 20, :kol = 24}, 
{:siz=>10, :heigth = 30, :wigth = 10, :kol = 24}, 
{:siz=>10, :heigth = 30, :wigth = 20, :kol = 33}, 
{:siz=>10, :heigth = 20, :wigth = 20, :kol = 3}, 
{:siz=>10, :heigth = 20, :wigth = 20, :kol = 5},... 

как создать массив или хэш с группой полей , например:

[{:siz=>10 => {:heigth=>"30" => {:wigth=>"20" => {:sum_kol => sum(kol)}}},   
{:siz=>10 => {:heigth=>"30" => {:wigth=>"10" => {:sum_kol => sum(kol)}}}, 
{:siz=>10 => {:heigth=>"20" => {:wigth=>"20" => {:sum_kol => sum(kol)}}}] 
+2

Ваш вопрос не очень ясен. Можете ли вы предоставить лучший пример того, что ваши входы и ожидаемые результаты? – d11wtq

+0

отредактировал, теперь okey? – memoris

+0

: siz,: heigth,: wigth, and: kol Предполагается, что: размер,: высота,: ширина и: col? Я не понимаю вашу структуру гнездования; вы фактически не объединяете все элементы с одинаковым размером в один элемент, поэтому вложение кажется несколько бессмысленным. Похоже, что имеет смысл иметь что-то вроде '{10 => {20 => {20 => sum}, 30 => {10 => sum, 20 => sum}}}' –

ответ

5

Если это исходит из базы данных, я хотел бы посмотреть на использование базы данных, чтобы сделать гр для вас и для обобщения. Но вот один из способов сделать это в Ruby:

raw_data = [ {:siz=>10, :heigth => 30, :wigth =>20, :kol =>24}, 
      {:siz=>10, :heigth =>30, :wigth =>10, :kol =>24}, 
      {:siz=>10, :heigth =>30, :wigth =>20, :kol =>33}, 
      {:siz=>10, :heigth =>20, :wigth =>20, :kol =>3}, 
      {:siz=>10, :heigth =>20, :wigth =>20, :kol =>5} ] 

# create a hash that defaults to three levels of nested hash values, 
# with 0s at the leaves 
summary = Hash.new do Hash.new do Hash.new do 0 end end end  

# populate it 
raw_data.each do |rec| 
    size, height, width, col = rec.values_at(:siz,:heigth,:wigth,:kol) 
    summary[size][height][width] += col 
end 

summary # => {10=>{30=>{20=>57, 10=>24}, 20=>{20=>8}}} 

Обычно это было бы более идиоматических в Рубине использовать inject/reduce вместо инициализации + обновления цикла:

summary = raw_data.reduce(Hash.new do Hash.new do Hash.new do 0 end end end) 
do |summary,rec| 
    size, height, width, col = rec.values_at(:siz,:heigth,:wigth,:kol) 
    summary[size][height][width] += col 
    summary 
end 

Но по умолчанию-Ладена хэш и необходимость вернуть хэш в конце блока сокращения, я думаю, что исходная версия здесь чище.

+0

Очень красиво @MarkReed. Но values_at не ошибка метода. Я реорганизую эту строку. Спасибо. – memoris

+0

? values_at определенно является допустимым методом для хэшей в ruby ​​1.8+. Если у вас возникнут проблемы, мы можем запустить сеанс чата. –

+0

Спасибо, переменная, мы решили проблему, переходим. – memoris