i have this code
type key struct {
account string
quantity float64
}
type invoice_tag struct {
account string
value_after_discount float64
value float64
price float64
total_discount float64
discount float64
quantity float64
}
invoice := []invoice_tag{{"Cash", 1024, 1024, 1, 0, 0, 1024}, {"Service Revenue", 0, 2048, 2, 0, 0, 1024}, {"Service Revenue", 0, 0, 0, 1024, 1, 1024}}
m := map[key][5]float64{}
for _, i := range invoice {
m[key{i.account, i.quantity}] = [5]float64{i.value_after_discount, i.value, i.price, i.total_discount, i.discount}
}
fmt.Println(m)
i want to group by account
and quantity
and to sum value_after_discount
with value_after_discount
and value
with value
and price
with price
and total_discount
with total_discount
and discount
with discount
. and the output should be
map[{Cash 1024}:[1024 1024 1 0 0] {Service Revenue 1024}:[1024 2048 2 1024 1]]
https://play.golang.org/p/KKTmovpfN1z
CodePudding user response:
Use a struct as the composite key with account
and quantity
fields. Note: float number comparisons may surprise you, if quantity
is an integer number, you should use an integer number (e.g. int
)!
Use a struct that holds the values you want to sum. For simplicity, I'll use invoice_tag
for this because it contains all the required fields, but you may create a separate struct too to your liking.
I'll store a pointer to this struct in the map, so when I update it in each iteration, I don't have to store the new value.
For example:
m := map[key]*invoice_tag{}
for _, i := range invoice {
k := key{i.account, i.quantity}
sums := m[k]
if sums == nil {
sums = &invoice_tag{}
m[k] = sums
}
sums.value_after_discount = i.value_after_discount
sums.value = i.value
sums.price = i.price
sums.total_discount = i.total_discount
sums.discount = i.discount
}
for k, v := range m {
fmt.Printf("key: %v, sums: value_after_discount: %f, value: %f, price: %f, total_discount: %f, discount: %f\n",
k, v.value_after_discount, v.value, v.price, v.total_discount, v.discount)
}
This will output (try it on the Go Playground):
key: {Cash 1024}, sums: value_after_discount: 1024.000000, value: 1024.000000, price: 1.000000, total_discount: 0.000000, discount: 0.000000
key: {Service Revenue 1024}, sums: value_after_discount: 0.000000, value: 2048.000000, price: 2.000000, total_discount: 1024.000000, discount: 1.000000
Again: this works because the input data we used contains identical floating point constant literals (which result in identical float64
value). In practice the grouping may give incorrect results due to IEEE 754 floating point quirks. I recommend using int
for quantity if possible. If not possible, then format the quantities to identical format (including certain digit rounding).