2014-02-03 3 views
2

У меня есть 2 массивы хэшей:Объединение нескольких массивов хэшей и выполнять вычисление

charges = [ 
    {:created=>"2014-01-28", :charge=>43677}, 
    {:created=>"2014-01-29", :charge=>37980}, 
    {:created=>"2014-01-30", :charge=>87354}, 
    {:created=>"2014-01-31", :charge=>43677} 
] 

fees = [ 
    {:created=>"2014-01-28", :fee=>3230}, 
    {:created=>"2014-01-29", :fee=>2380}, 
    {:created=>"2014-01-30", :fee=>2210}, 
    {:created=>"2014-01-31", :fee=>1870} 
] 

Что мне нужно сделать, это взять fees и вычесть их из charges на каждую дату и выдать вычисленный сумму, как так :

totals = [ 
    {:created=>"2014-01-28", :amount=>40447}, 
    {:created=>"2014-01-29", :amount=>35600}, 
    {:created=>"2014-01-30", :amount=>85144}, 
    {:created=>"2014-01-31", :amount=>41870} 
] 

Обратите внимание, что не может быть как плата, так и плата за данный день. Поэтому в случае без комиссии вы просто ничего не вычтите (или вы вычтите 0). В случае сборов, но без сборов, у вас будет отрицательное число.

+0

Не вы просто задать подобный вопрос [] (http://stackoverflow.com/questions/21535854/group и-сумма-массив из-хэшей по дате)? Ответ очень похож. –

+0

@ChrisHeald Это занимает 2 отдельных массива хэшей., Нахожу совпадающую дату для каждого, вычитая числа, а затем выплевывая новый массив хэшей. Предыдущий вопрос включал один массив хэшей. – Shpigford

ответ

3

Я бы

charges = [ 
    {:created=>"2014-01-28", :charge=>43677}, 
    {:created=>"2014-01-29", :charge=>37980}, 
    {:created=>"2014-01-30", :charge=>87354}, 
    {:created=>"2014-01-31", :charge=>43677} 
] 

fees = [ 
    {:created=>"2014-01-28", :fee=>3230}, 
    {:created=>"2014-01-29", :fee=>2380}, 
    {:created=>"2014-01-30", :fee=>2210}, 
    {:created=>"2014-01-31", :fee=>1870} 
] 

total = (fees + charges).group_by{ |h| h[:created] }.map do |k,v| 
    val_hsh = v.each_with_object({}) do |h1,h2| 
    h1[:fee] ? h2[:fee] = h1[:fee] : h2[:charge] = h1[:charge] 
    end 
    {created: k, amount: val_hsh[:charge] - val_hsh[:fee]} 
end 

total 
# => [{:created=>"2014-01-28", :amount=>40447}, 
#  {:created=>"2014-01-29", :amount=>35600}, 
#  {:created=>"2014-01-30", :amount=>85144}, 
#  {:created=>"2014-01-31", :amount=>41807}] 

обновление

charges = [ 
    {:created=>"2014-01-28", :charge=>43677}, 
    {:created=>"2014-01-29", :charge=>37980}, 
    {:created=>"2014-01-30", :charge=>87354}, 
    {:created=>"2014-01-31", :charge=>0} 
] 

fees = [ 
    {:created=>"2014-01-28", :fee=>3230}, 
    {:created=>"2014-01-29", :fee=>0}, 
    {:created=>"2014-01-30", :fee=>2210}, 
    {:created=>"2014-01-31", :fee=>1870} 
] 

total = (fees + charges).group_by{ |h| h[:created] }.map do |k,v| 
    val_hsh = v.each_with_object({}) do |h1,h2| 
    h1[:fee] ? h2[:fee] = h1[:fee] : h2[:charge] = h1[:charge] 
    end 
    {created: k, amount: val_hsh[:charge] - val_hsh[:fee]} 
end 

total 
# => [{:created=>"2014-01-28", :amount=>40447}, 
#  {:created=>"2014-01-29", :amount=>37980}, 
#  {:created=>"2014-01-30", :amount=>85144}, 
#  {:created=>"2014-01-31", :amount=>-1870}] 
+0

Ницца! Однако плата должна быть вычтена из сбора, а не добавлена. –

+0

@WayneConrad извините .. делаю .. :) –

+0

Есть ли способ получить результат как вычитаемое значение, как у меня в моем примере, а не в виде массива обоих значений? – Shpigford

0

Если вы хотите сгруппировать по датам, которые отсутствуют в любом массиве, вы можете сделать, как @ArupRakshit сделал выше: группа по дата затем вычисляется.

В противном случае, я предлагаю вам указать идентификатор для идентификации записей в случае, если есть несколько записей в день - если вы не ушли от него намеренно по дизайну.

Вы можете пойти со следующим, предполагая, что массивы сортируются по идентификатору:

charges.zip(fees).collect { |charge, fee| { :created => charge[:created], :amount => charge[:charge] - fee[:fee] } } 

=> [{:created=>"2014-01-28", :amount=>40447}, 
{:created=>"2014-01-29", :amount=>35600}, 
{:created=>"2014-01-30", :amount=>85144}, 
{:created=>"2014-01-31", :amount=>41807}] 
Смежные вопросы