英文:
Averaging by time in a slice of structs with Go
问题
我正在以一种基本的方式按小时对结构体切片中的值进行平均,我想得到一种更通用的方法,可以按小时、天、周等进行平均。提前感谢大家。
package main
import (
"fmt"
"math/rand"
"time"
)
type Acc struct {
name string
money int
date time.Time
}
type Accs []Acc
const Tformat = "02/01/2006 15:04:05"
func main() {
var myaccs Accs
acc := 0
var loops int
var hour int
f1, _ := time.Parse(Tformat, "29/08/2013 00:00:19")
// 创建一个结构体切片
for i := 0; i < 10; i++ {
f1 = f1.Add(20 * time.Minute) // 每个记录增加20分钟
myaccs = append(myaccs, Acc{name: "christian", money: rand.Intn(200), date: f1})
fmt.Printf("添加到切片中:%v, %d, %s\n", myaccs[i].name, myaccs[i].money, myaccs[i].date)
}
// 平均值计算
for _, v := range myaccs {
if acc == 0 {
hour = v.date.Hour()
acc += v.money
loops++
} else {
if v.date.Hour() == hour {
acc += v.money
loops++
} else {
fmt.Printf("小时 %d 的平均金额:%d\n", hour, acc/loops) //->Action
acc = v.money
hour = v.date.Hour()
loops = 1
}
}
//fmt.Println(v, acc, loops, hour)
}
fmt.Printf("小时 %d 的平均金额:%d\n", hour, acc/loops) //->Action
}
注意:Money变量只是一个示例,是一个整数。
注意2:我假设数据已经排序好了。
Playground:
http://play.golang.org/p/lL3YDD4ecE
英文:
I'm averaging values by hour in a slice of structs in a basic way, and I would get a better aproach to it in order to get a most generic funcion that can get averaging by hours, days, weeks, etc. Thanks in advance to everybody.
package main
import (
"fmt"
"math/rand"
"time"
)
type Acc struct {
name string
money int
date time.Time
}
type Accs []Acc
const Tformat = "02/01/2006 15:04:05"
func main() {
var myaccs Accs
acc := 0
var loops int
var hour int
f1, _ := time.Parse(Tformat, "29/08/2013 00:00:19")
// Creating a Slice of structs
for i := 0; i < 10; i++ {
f1 = f1.Add(20 * time.Minute) //adding 20 minutes to every record
myaccs = append(myaccs, Acc{name: "christian", money: rand.Intn(200), date: f1})
fmt.Printf("Added to slice: %v, %d, %s\n", myaccs[i].name, myaccs[i].money, myaccs[i].date)
}
// Averaging
for _, v := range myaccs {
if acc == 0 {
hour = v.date.Hour()
acc += v.money
loops++
} else {
if v.date.Hour() == hour {
acc += v.money
loops++
} else {
fmt.Printf("Average money value to hour %d : %d\n", hour, acc / loops) //->Action
acc = v.money
hour = v.date.Hour()
loops = 1
}
}
//fmt.Println(v, acc, loops, hour)
}
fmt.Printf("Average money value to hour %d : %d\n", hour, acc / loops)//->Action
}
Note: Money variable is a int like a example only..<br>
Note2: I'm considering that the data are already sorted<br>
Playground:
http://play.golang.org/p/lL3YDD4ecE
答案1
得分: 2
时间数学问题充满了风险,但是这里是一种解决该问题的方法:
type Snapshot struct {
Value AccountValue
At time.Time
}
type Granularity struct {
Name string
DateIncrement [3]int
DurIncrement time.Duration
DateFormat string
}
type Graph struct {
Granularity
Values map[string][]AccountValue
}
func (g *Graph) Add(snaps []Snapshot) {
if g.Values == nil {
g.Values = map[string][]AccountValue{}
}
for _, s := range snaps {
key := g.Format(s.At)
g.Values[key] = append(g.Values[key], s.Value)
}
}
func (g *Graph) Get(from, to time.Time) (snaps []Snapshot) {
from, to = g.Truncate(from), g.Truncate(to)
for cur := from; !to.Before(cur); cur = g.AddTo(cur) {
var avg, denom AccountValue
for _, v := range g.Values[g.Format(cur)] {
avg += v
denom += 1
}
if denom > 0 {
avg /= denom
}
snaps = append(snaps, Snapshot{
Value: avg,
At: cur,
})
}
return snaps
}
完整代码请参见Playground。
英文:
Time math is frought with peril, but here is one way to approach the problem:
type Snapshot struct {
Value AccountValue
At time.Time
}
type Granularity struct {
Name string
DateIncrement [3]int
DurIncrement time.Duration
DateFormat string
}
type Graph struct {
Granularity
Values map[string][]AccountValue
}
func (g *Graph) Add(snaps []Snapshot) {
if g.Values == nil {
g.Values = map[string][]AccountValue{}
}
for _, s := range snaps {
key := g.Format(s.At)
g.Values[key] = append(g.Values[key], s.Value)
}
}
func (g *Graph) Get(from, to time.Time) (snaps []Snapshot) {
from, to = g.Truncate(from), g.Truncate(to)
for cur := from; !to.Before(cur); cur = g.AddTo(cur) {
var avg, denom AccountValue
for _, v := range g.Values[g.Format(cur)] {
avg += v
denom += 1
}
if denom > 0 {
avg /= denom
}
snaps = append(snaps, Snapshot{
Value: avg,
At: cur,
})
}
return snaps
}
Full code in Playground
答案2
得分: 1
对于未排序的数据
首先,在类型 Accs []Acc 上实现排序接口。然后,你可以根据小时、天、周等进行排序。
对于已排序的数据
在 Accs 上创建一个 GroupBy 方法。
func (accs Accs) GroupBy(p func(Acc,Acc) bool) [][]Accs {
// 在这里编写循环/比较/分组代码
}
使用谓词函数 p 来传递特定于分组的代码,以比较两个 Acc 结构,看它们是否应该放在同一组中。
一旦 Accs 被分组,你就可以进行求和、平均值等操作。
英文:
For unsorted data
Start by implementing the sort interface on the type Accs []Acc. Then you can easily sort by hours, days, weeks.
For sorted data
Create a GroupBy method on Accs.
func (accs Accs) GroupBy(p func(Acc,Acc) bool) [][]Accs {
// your looping/comparing/grouping code goes here
}
Use the predicate function p to pass in group specific code for comparing two Acc structs to see if they should go in the same group.
Once the Accs are in groups you can sum, avg etc.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论