假设我有一个结构
type row struct {
f1, f2, f3 string
v int64
}
我们可以把它想象成表中的一行。
此外,我需要实现一个可以像以下查询那样进行聚合的函数:
SELECT f1, f2, f3, SUM(v) FROM table GROUP BY f1, f2, f3
所以,我必须实现功能:
type key struct {
f1, f2, f3 string
}
func aggregate(t []row) map[key]int64
或者如果可以的话
func aggregate(t []row) map[string]row
其中映射键为f1 + f2 + f3
func aggregate(t []row) []row
如果结果将包含唯一的f1,f2,f3组合(DISTINCT f1,f2,f3),也可以使用
我有两个变体:
func aggregate1(t []row) map[key]int64 {
res := map[key]int64{}
for _, r := range t {
res[key{r.f1, r.f2, r.f3}] += r.v
}
return res
}
func aggregate2(t []row) map[string]*row {
res := map[string]*row{}
for _, r := range t {
var sb strings.Builder
sb.WriteString(r.f1)
sb.WriteString("#")
sb.WriteString(r.f2)
sb.WriteString("#")
sb.WriteString(r.f3)
id := sb.String()
t := res[id]
if t == nil {
t = &row{f1: r.f1, f2: r.f2, f3: r.f3, v: 0}
res[id] = t
}
t.v += r.v
}
return res
}
第一个变体在https://golang.org/pkg/runtime/?m=all#mapassign(runtime.mapassign)中花费太多时间
第二个变体的想法是使用更快的https://golang.org/pkg/runtime/?m=all#mapassign_faststr(runtime.mapassign_faststr),但是strings.Builder.WriteString消除了runtime.mapassign_faststr的所有好处:(
那么,您能建议更多有关如何实现此聚合的想法吗?
我正在考虑如何在第二个变体中有效地计算“ id”。它应该是唯一的。我的变体是唯一的,因为f1,f2和f3不能包含“#”字符。