dongtan3395 2017-10-23 14:43
浏览 44
已采纳

在切片中仅保留n个元素

Please see this playground. As you can see I have a slice within a struct. I also have a method which can be used to add a new element to the slice. This works fine.

But now my problem is that I want to extend the method so that it leaves n elements of the slice. So when adding a new element, the "oldest" should be removed and the new one should be added.

How can I do this? Aren't there out-of-the-box packages which I can use?

  • 写回答

3条回答 默认 最新

  • dotws86260 2017-10-23 21:05
    关注

    For example,

    addimport.go:

    package main
    
    import (
        "fmt"
        "time"
    )
    
    type Statistics struct {
        LastScan time.Time
        Imports  []Import
    }
    
    type Import struct {
        text string
    }
    
    func (s *Statistics) AddImport(i Import) {
        // only the last n entries are kept
        const n = 2 // n > 0 and small
        if len(s.Imports) >= n {
            copy(s.Imports, s.Imports[len(s.Imports)-n+1:])
            s.Imports = s.Imports[:n-1]
        }
        s.Imports = append(s.Imports, i)
    }
    
    func main() {
        s := Statistics{}
        fmt.Println(len(s.Imports), cap(s.Imports), s.Imports)
        s.AddImport(Import{text: "myText1"})
        s.AddImport(Import{text: "myText2"})
        s.AddImport(Import{text: "myText3"})
        fmt.Println(len(s.Imports), cap(s.Imports), s.Imports)
    }
    

    Playground: https://play.golang.org/p/204-uB8Zls

    Output:

    0 0 []
    2 2 [{myText2} {myText3}]
    

    Code should be reasonably efficient. Go has a benchmark package. Here are the benchmark results for the solutions from peterSO, Kaedys, and gonutz.

    $ go test -bench=. addimport_test.go
    BenchmarkAddImport/PeterSO-4   100000   16145 ns/op      96 B/op     3 allocs/op
    BenchmarkAddImport/Kaedys-4     30000   59344 ns/op   32032 B/op   502 allocs/op
    BenchmarkAddImport/Gonutz-4     30000   60447 ns/op   32032 B/op   502 allocs/op
    

    addimport_test.go:

    package main
    
    import (
        "testing"
        "time"
    )
    
    type Statistics struct {
        LastScan time.Time
        Imports  []Import
    }
    
    type Import struct {
        text string
    }
    
    func (s *Statistics) AddImportPeterSO(i Import) {
        // only the last n entries are kept
        const n = 2 // n > 0 and small
        if len(s.Imports) >= n {
            copy(s.Imports, s.Imports[len(s.Imports)-n+1:])
            s.Imports = s.Imports[:n-1]
        }
        s.Imports = append(s.Imports, i)
    }
    
    const numberToKeep = 2
    
    func (s *Statistics) AddImportKaedys(i Import) {
        s.Imports = append(s.Imports, i)
        if len(s.Imports) > numberToKeep {
            s.Imports = s.Imports[len(s.Imports)-numberToKeep:]
        }
    }
    
    func (s *Statistics) AddImportGonutz(i Import) {
        s.Imports = append(s.Imports, i)
        const max = 2
        if len(s.Imports) > max {
            s.Imports = s.Imports[1:]
        }
    }
    
    func benchmarkAddImport(b *testing.B, addImport func(*Statistics, Import)) {
        b.ReportAllocs()
        for i := 0; i < b.N; i++ {
            var s Statistics
            for j := 0; j < 1000; j++ {
                addImport(&s, Import{})
            }
        }
    }
    
    func BenchmarkAddImport(b *testing.B) {
        b.Run("PeterSO", func(b *testing.B) {
            benchmarkAddImport(b, (*Statistics).AddImportPeterSO)
        })
        b.Run("Kaedys", func(b *testing.B) {
            benchmarkAddImport(b, (*Statistics).AddImportKaedys)
        })
        b.Run("Gonutz", func(b *testing.B) {
            benchmarkAddImport(b, (*Statistics).AddImportGonutz)
        })
    }
    

    Playground: https://play.golang.org/p/Q2X_T5Vofe


    The general form of this problem is a circular buffer: Circular buffer.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c