zoukankan      html  css  js  c++  java
  • Go语言中使用切片(slice)实现一个Vector容器

    Go语言中的切片(slice)和一些内置函数能实现其他语言容器类Array、Vector的功能,但是Go内置语言包container里只提供了list、heap、ring三种容器,缺少vector容器,在实际的项目中为使用方便有必要包装一个vector,提供vector的常见功能。

    C++、Java、C#等语言支持泛型,Go语言不支持泛型,可以用 interface{} 提供类似泛型的支持。下面是vector容器代码

    package vector
    
    import (
        "reflect"
    )
    
    // 小写 只能通过工厂函数创建
    type vector struct {
        values []interface{}
    }
    
    // 创建工厂函数
    func New(cap int) *vector {
        this := new(vector)
        this.values = make([]interface{}, 0, cap)
    
        return this
    }
    
    func (this *vector) IsEmpty() bool {
        return len(this.values) == 0
    }
    
    // 元素数量
    func (this *vector) Size() int {
        return len(this.values)
    }
    
    // 追加单个元素
    func (this *vector) Append(value interface{}) bool {
        this.values = append(this.values, value)
        return true
    }
    
    // 追加元素切片
    func (this *vector) AppendAll(values []interface{}) bool {
        if values == nil || len(values) < 1 {
            return false
        }
        this.values = append(this.values, values...)
        return true
    }
    
    // 插入单个元素
    func (this *vector) Insert(index int, value interface{}) bool {
        if index < 0 || index >= len(this.values) {
            return false
        }
        this.values = append(this.values[:index], append([]interface{}{value}, this.values[index:]...)...)
        return true
    }
    
    // 插入元素切片
    func (this *vector) InsertAll(index int, values []interface{}) bool {
        if index < 0 || index >= len(this.values) || values == nil || len(values) < 1 {
            return false
        }
        this.values = append(this.values[:index], append(values, this.values[index:]...)...)
        return true
    }
    
    // 移除
    func (this *vector) Remove(index int) bool {
        if index < 0 || index >= len(this.values) {
            return false
        }
        // 重置为 nil 防止内存泄漏
        this.values[index] = nil
        this.values = append(this.values[:index], this.values[index+1:]...)
        return true
    }
    
    // 范围移除 从 fromIndex(包含) 到 toIndex(不包含) 之间的元素
    func (this *vector) RemoveRange(fromIndex, toIndex int) bool {
        if fromIndex < 0 || fromIndex >= len(this.values) || toIndex > len(this.values) || fromIndex > toIndex {
            return false
        }
        // 重置为 nil 防止内存泄漏
        for i := fromIndex; i < toIndex; i++ {
            this.values[i] = nil
        }
        this.values = append(this.values[:fromIndex], this.values[toIndex:]...)
        return true
    }
    
    // 全部移除
    func (this *vector) RemoveAll() {
        // 重置为 nil 防止内存泄漏
        for i := 0; i < this.Size(); i++ {
            this.values[i] = nil
        }
        this.values = this.values[0:0]
    }
    
    func (this *vector) getIndex(value interface{}) int {
        for i := 0; i < len(this.values); i++ {
            if reflect.DeepEqual(this.values[i], value) {
                return i
            }
        }
        return -1
    }
    
    // 是否存在该元素值
    func (this *vector) Contains(value interface{}) bool {
        return this.getIndex(value) >= 0
    }
    
    // 获取元素值第一次出现的索引
    func (this *vector) IndexOf(value interface{}) int {
        return this.getIndex(value)
    }
    
    // 获取元素值最后一次出现的索引
    func (this *vector) LastIndexOf(value interface{}) int {
        for i := len(this.values) - 1; i >= 0; i-- {
            if reflect.DeepEqual(this.values[i], value) {
                return i
            }
        }
        return -1
    }
    
    // 得到索引对应的元素值
    func (this *vector) GetValue(index int) interface{} {
        if index < 0 || index >= len(this.values) {
            return nil
        }
        return this.values[index]
    }
    
    // 设置值
    func (this *vector) SetValue(index int, value interface{}) bool {
        if index < 0 || index >= len(this.values) {
            return false
        }
        this.values[index] = value
        return true
    }
    
    func (this *vector) ToArray() []interface{} {
        dst := make([]interface{}, this.Size())
        copy(dst, this.values)
        return dst
    }
    

    vector内部使用切片(slice)保存元素值,元素类型 interface{},泛型。getIndex()方法使用reflect.DeepEqual()函数对元素值作深度比较。上述代码只提供了vector容器常见功能,更多的功能可以根据需要添加,比如有的时候需要对容器中的元素排序,则可以添加排序方法。

    一些方法简单返回bool值表示成功或失败,可以根据需要增加一个error返回值指明失败的详细原因。

    需要注意的事项是Remove、RemoveRange、RemoveAll方法内把元素移走时避免内存泄露。

    下面是测试代码

    func testVector() {
        v := vector.New(5)
        for i := 0; i < 6; i++ {
            v.Append(i)
        }
        fmt.Println(*v)
        fmt.Println(v.IsEmpty())
        v.Insert(1, 10)
        v.Insert(20, 20)
        fmt.Println(*v)
        v.Remove(-1)
        v.Remove(1)
        v.Remove(100)
        fmt.Println(*v)
        fmt.Println(v.IndexOf(3))
        fmt.Println(v.IndexOf(300))
        fmt.Println(v.GetValue(1))
        fmt.Println(v.GetValue(100))
        v.SetValue(-1, -1)
        v.SetValue(1, 11)
        v.SetValue(100, 101)
        fmt.Println(*v)
    
        v.RemoveAll()
        fmt.Println(v.IsEmpty())
        fmt.Println(v.Size())
    
        v.Append(22)
        fmt.Println(*v)
    }
    

    测试代码覆盖了部分可能的情况,创建函数New的cap参数指明容器的初始容量。

    上述测试代码只写了int类型的元素,其他string、float、array、map、struct、slice、vector等类型类似。

  • 相关阅读:
    DELPHI 表格控件 DBGridEh 属性设置详解
    Delphi保存网页中的图片
    Delphi 文件转换Base64
    CEF 各个版本适应的平台参考表
    让dcef3支持mp3和h.264 mp4解码播放
    Cef 重写alert与confirm弹窗
    dcef3 基本使用经验总结
    CEF3 命令行 CefCommandLine 所有选项 与 开发中使用的测试网址
    php连接sql server(win10+phpstudy+navicat+php+sql server)
    C语言随机数
  • 原文地址:https://www.cnblogs.com/aiandbigdata/p/10913336.html
Copyright © 2011-2022 走看看