如何在golang中按多个值分组并对多个值求和
how to group by multiple value and sum multiple value in golang
我有这个代码
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)
我想按 account
和 quantity
分组,并将 value_after_discount
与 value_after_discount
和 value
与 value
和 [= 求和18=] 与 price
和 total_discount
与 total_discount
和 discount
与 discount
。输出应该是
map[{Cash 1024}:[1024 1024 1 0 0] {Service Revenue 1024}:[1024 2048 2 1024 1]]
使用结构作为具有 account
和 quantity
字段的复合键。注意:浮点数比较可能会让你大吃一惊,如果quantity
是整数,你应该使用整数(例如int
)!
使用包含要求和的值的结构。为简单起见,我将为此使用 invoice_tag
,因为它包含所有必需的字段,但您也可以根据自己的喜好创建一个单独的结构。
我将在映射中存储指向该结构的指针,因此当我在每次迭代中更新它时,我不必存储新值。
例如:
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)
}
这将输出(在 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
再次:这是有效的,因为我们使用的输入数据包含相同的浮点常量文字(导致相同的 float64
值)。实际上,由于 IEEE 754 浮点怪癖,分组可能会给出不正确的结果。如果可能,我建议使用 int
作为数量。如果不可能,则将数量格式化为相同的格式(包括某些数字舍入)。
我有这个代码
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)
我想按 account
和 quantity
分组,并将 value_after_discount
与 value_after_discount
和 value
与 value
和 [= 求和18=] 与 price
和 total_discount
与 total_discount
和 discount
与 discount
。输出应该是
map[{Cash 1024}:[1024 1024 1 0 0] {Service Revenue 1024}:[1024 2048 2 1024 1]]
使用结构作为具有 account
和 quantity
字段的复合键。注意:浮点数比较可能会让你大吃一惊,如果quantity
是整数,你应该使用整数(例如int
)!
使用包含要求和的值的结构。为简单起见,我将为此使用 invoice_tag
,因为它包含所有必需的字段,但您也可以根据自己的喜好创建一个单独的结构。
我将在映射中存储指向该结构的指针,因此当我在每次迭代中更新它时,我不必存储新值。
例如:
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)
}
这将输出(在 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
再次:这是有效的,因为我们使用的输入数据包含相同的浮点常量文字(导致相同的 float64
值)。实际上,由于 IEEE 754 浮点怪癖,分组可能会给出不正确的结果。如果可能,我建议使用 int
作为数量。如果不可能,则将数量格式化为相同的格式(包括某些数字舍入)。