Reputation: 27
I have an input as follows:
input = [
["account1",10,"Dr"],
["account1",20,"Dr"],
["account2",15,"Cr"],
["account1",25,"Cr"],
["account2",10,"Dr"],
["account1",10,"Cr"]
]
I am trying to get the sums by account and transaction type, i.e., Dr
or Cr
. I need an output as below:
output = {
["account1","Dr"] => 30,
["account1","Cr"] => 35,
["account2","Dr"] => 10,
["account2","Cr"] => 15
}
I can sum the amount based on only account using:
input.each_with_object(Hash.new(0)) {|(f,g), h| h[f] += g}
# => {"account1"=>65, "account2"=>25}
Upvotes: 0
Views: 94
Reputation: 110675
input.group_by { |acc,_,title| [acc, title] }.
transform_values { |v| v.sum { |a| a[1] } }
#=> {["account1", "Dr"]=>30, ["account2", "Cr"]=>15, ["account1", "Cr"]=>35,
# ["account2", "Dr"]=>10}
The first step is the following.
input.group_by { |acc,_,title| [acc, title] }
#=> {
# ["account1", "Dr"]=>[["account1", 10, "Dr"], ["account1", 20, "Dr"]],
# ["account2", "Cr"]=>[["account2", 15, "Cr"]],
# ["account1", "Cr"]=>[["account1", 25, "Cr"], ["account1", 10, "Cr"]],
# ["account2", "Dr"]=>[["account2", 10, "Dr"]]
# }
Upvotes: 2
Reputation: 739
You can do so:
input.each_with_object(Hash.new(0)) {|(f,g,i), h| h[[f,i]] += g}
=> {["account1", "Dr"]=>30, ["account2", "Cr"]=>15, ["account1", "Cr"]=>35, ["account2", "Dr"]=>10}
Upvotes: 4
Reputation: 10107
output = Hash.new(0) # set a default value of zero, avoiding nil
input.each do |account, amount, transaction|
output[[account, transaction]] += amount
end
output # {["account1", "Dr"]=>30, ["account2", "Cr"]=>15, ["account1", "Cr"]=>35, ["account2", "Dr"]=>10}
Upvotes: 1