在Go语言中,对结构体切片按时间进行平均的方法是什么?

huangapple go评论187阅读模式
英文:

Averaging by time in a slice of structs with Go

问题

我正在以一种基本的方式按小时对结构体切片中的值进行平均,我想得到一种更通用的方法,可以按小时、天、周等进行平均。提前感谢大家。

  1. package main
  2. import (
  3. "fmt"
  4. "math/rand"
  5. "time"
  6. )
  7. type Acc struct {
  8. name string
  9. money int
  10. date time.Time
  11. }
  12. type Accs []Acc
  13. const Tformat = "02/01/2006 15:04:05"
  14. func main() {
  15. var myaccs Accs
  16. acc := 0
  17. var loops int
  18. var hour int
  19. f1, _ := time.Parse(Tformat, "29/08/2013 00:00:19")
  20. // 创建一个结构体切片
  21. for i := 0; i < 10; i++ {
  22. f1 = f1.Add(20 * time.Minute) // 每个记录增加20分钟
  23. myaccs = append(myaccs, Acc{name: "christian", money: rand.Intn(200), date: f1})
  24. fmt.Printf("添加到切片中:%v, %d, %s\n", myaccs[i].name, myaccs[i].money, myaccs[i].date)
  25. }
  26. // 平均值计算
  27. for _, v := range myaccs {
  28. if acc == 0 {
  29. hour = v.date.Hour()
  30. acc += v.money
  31. loops++
  32. } else {
  33. if v.date.Hour() == hour {
  34. acc += v.money
  35. loops++
  36. } else {
  37. fmt.Printf("小时 %d 的平均金额:%d\n", hour, acc/loops) //->Action
  38. acc = v.money
  39. hour = v.date.Hour()
  40. loops = 1
  41. }
  42. }
  43. //fmt.Println(v, acc, loops, hour)
  44. }
  45. fmt.Printf("小时 %d 的平均金额:%d\n", hour, acc/loops) //->Action
  46. }

注意: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.

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;math/rand&quot;
  5. &quot;time&quot;
  6. )
  7. type Acc struct {
  8. name string
  9. money int
  10. date time.Time
  11. }
  12. type Accs []Acc
  13. const Tformat = &quot;02/01/2006 15:04:05&quot;
  14. func main() {
  15. var myaccs Accs
  16. acc := 0
  17. var loops int
  18. var hour int
  19. f1, _ := time.Parse(Tformat, &quot;29/08/2013 00:00:19&quot;)
  20. // Creating a Slice of structs
  21. for i := 0; i &lt; 10; i++ {
  22. f1 = f1.Add(20 * time.Minute) //adding 20 minutes to every record
  23. myaccs = append(myaccs, Acc{name: &quot;christian&quot;, money: rand.Intn(200), date: f1})
  24. fmt.Printf(&quot;Added to slice: %v, %d, %s\n&quot;, myaccs[i].name, myaccs[i].money, myaccs[i].date)
  25. }
  26. // Averaging
  27. for _, v := range myaccs {
  28. if acc == 0 {
  29. hour = v.date.Hour()
  30. acc += v.money
  31. loops++
  32. } else {
  33. if v.date.Hour() == hour {
  34. acc += v.money
  35. loops++
  36. } else {
  37. fmt.Printf(&quot;Average money value to hour %d : %d\n&quot;, hour, acc / loops) //-&gt;Action
  38. acc = v.money
  39. hour = v.date.Hour()
  40. loops = 1
  41. }
  42. }
  43. //fmt.Println(v, acc, loops, hour)
  44. }
  45. fmt.Printf(&quot;Average money value to hour %d : %d\n&quot;, hour, acc / loops)//-&gt;Action
  46. }

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

时间数学问题充满了风险,但是这里是一种解决该问题的方法:

  1. type Snapshot struct {
  2. Value AccountValue
  3. At time.Time
  4. }
  5. type Granularity struct {
  6. Name string
  7. DateIncrement [3]int
  8. DurIncrement time.Duration
  9. DateFormat string
  10. }
  11. type Graph struct {
  12. Granularity
  13. Values map[string][]AccountValue
  14. }
  15. func (g *Graph) Add(snaps []Snapshot) {
  16. if g.Values == nil {
  17. g.Values = map[string][]AccountValue{}
  18. }
  19. for _, s := range snaps {
  20. key := g.Format(s.At)
  21. g.Values[key] = append(g.Values[key], s.Value)
  22. }
  23. }
  24. func (g *Graph) Get(from, to time.Time) (snaps []Snapshot) {
  25. from, to = g.Truncate(from), g.Truncate(to)
  26. for cur := from; !to.Before(cur); cur = g.AddTo(cur) {
  27. var avg, denom AccountValue
  28. for _, v := range g.Values[g.Format(cur)] {
  29. avg += v
  30. denom += 1
  31. }
  32. if denom > 0 {
  33. avg /= denom
  34. }
  35. snaps = append(snaps, Snapshot{
  36. Value: avg,
  37. At: cur,
  38. })
  39. }
  40. return snaps
  41. }

完整代码请参见Playground

英文:

Time math is frought with peril, but here is one way to approach the problem:

  1. type Snapshot struct {
  2. Value AccountValue
  3. At time.Time
  4. }
  5. type Granularity struct {
  6. Name string
  7. DateIncrement [3]int
  8. DurIncrement time.Duration
  9. DateFormat string
  10. }
  11. type Graph struct {
  12. Granularity
  13. Values map[string][]AccountValue
  14. }
  15. func (g *Graph) Add(snaps []Snapshot) {
  16. if g.Values == nil {
  17. g.Values = map[string][]AccountValue{}
  18. }
  19. for _, s := range snaps {
  20. key := g.Format(s.At)
  21. g.Values[key] = append(g.Values[key], s.Value)
  22. }
  23. }
  24. func (g *Graph) Get(from, to time.Time) (snaps []Snapshot) {
  25. from, to = g.Truncate(from), g.Truncate(to)
  26. for cur := from; !to.Before(cur); cur = g.AddTo(cur) {
  27. var avg, denom AccountValue
  28. for _, v := range g.Values[g.Format(cur)] {
  29. avg += v
  30. denom += 1
  31. }
  32. if denom &gt; 0 {
  33. avg /= denom
  34. }
  35. snaps = append(snaps, Snapshot{
  36. Value: avg,
  37. At: cur,
  38. })
  39. }
  40. return snaps
  41. }

Full code in Playground

答案2

得分: 1

对于未排序的数据

首先,在类型 Accs []Acc 上实现排序接口。然后,你可以根据小时、天、周等进行排序。

对于已排序的数据

在 Accs 上创建一个 GroupBy 方法。

  1. func (accs Accs) GroupBy(p func(Acc,Acc) bool) [][]Accs {
  2. // 在这里编写循环/比较/分组代码
  3. }

使用谓词函数 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.

  1. func (accs Accs) GroupBy(p func(Acc,Acc) bool) [][]Accs {
  2. // your looping/comparing/grouping code goes here
  3. }

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.

huangapple
  • 本文由 发表于 2013年9月2日 22:20:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/18575358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定