GO:一系列独特的结构,有效的可重用实现

时间:2017-01-20 11:10:10

标签: go

我经常需要根据任意等于函数去掉重复项。 我需要实现:

  1. 快速且内存有效(不创建地图)
  2. 可重复使用且易于使用,想想slice.Sort()(github.com/bradfitz/slice)
  3. 不需要保留原始切片的顺序或保留原始切片
  4. 最好尽量减少复制
  5. 这可以在go中实现吗?为什么这个函数不属于某些我知道的库? 我正在寻找,例如godash(github.com/zillow/godash)实现使用map并且不允许任意更少和相等。

    这是它应该如何看起来像。 测试:

    import (
        "reflect"
        "testing"
    )
    
    type bla struct {
        ID string
    }
    
    type blas []bla
    
    func (slice blas) Less(i, j int) bool {
        return slice[i].ID < slice[j].ID
    }
    
    func (slice blas) EqualID(i, j int) bool {
        return slice[i].ID == slice[j].ID
    }
    
    func Test_Unique(t *testing.T) {
        input := []bla{bla{ID: "d"}, bla{ID: "a"}, bla{ID: "b"}, bla{ID: "a"}, bla{ID: "c"}, bla{ID: "c"}}
        expected := []bla{bla{ID: "a"}, bla{ID: "b"}, bla{ID: "c"}, bla{ID: "d"}}
        Unique(input, blas(input).Less, blas(input).EqualID)
        if !reflect.DeepEqual(expected, input) {
            t.Errorf("2: Expected: %v but was %v \n", expected, input)
        }
    }
    

    我认为需要用它来实现这个目标:

    • 只有切片作为数据结构,以保持简单和易于排序。
    • 一些反思 - 对我来说很难!因为我是新手。

2 个答案:

答案 0 :(得分:2)

选项

  • 您可以对切片进行排序并检查相邻节点创建 = O(n登录),查找 = O(日志n),插入 = O(n),删除 = O(n)
  • 您可以将树和原始切片一起使用创建 = O(n登录),查找 = O(日志n),插入 = O(log n),删除 = O(log n)

在树实现中,您可以只在树节点中放置索引,并使用为接口定义的Equal / Less函数来完成节点的评估。

以下是树的示例,这是播放link

您必须添加更多功能才能使其可用,并且代码不是缓存友好的,因此您可以改进代码以使其缓存友好

如何使用

  1. 使表示切片的类型实现Setter接口
  2. set:= NewSet(切片),创建切片
  3. 现在set.T只有唯一值索引
  4. Set实施更多功能以进行其他设置操作
  5. 代码

    type Set struct {
        T Tree
        Slice Setter
    }
    
    func NewSet(slice Setter) *Set {
        set := new(Set)
        set.T = Tree{nil, 0, nil}
        set.Slice = slice
        for i:=0;i < slice.Len();i++ {
            insert(&set.T, slice, i)
        }
        return set
    }
    
    type Setter interface {
        Len() int
        At(int) (interface{},error)
        Less(int, int) bool
        Equal(int, int) bool
    }
    
    
    // A Tree is a binary tree with integer values.
    type Tree struct {
        Left  *Tree
        Value int
        Right *Tree
    }
    
    func insert(t *Tree, Setter Setter, index int) *Tree {
        if t == nil {
            return &Tree{nil, index, nil}
        }
        if Setter.Equal(t.Value, index) {
            return t
        }
    
        if Setter.Less(t.Value, index) {
            t.Left = insert(t.Left, Setter, index)
            return t
        }
        t.Right = insert(t.Right, Setter, index)
        return t
    }
    

答案 1 :(得分:0)

Bloom过滤器经常用于相等性测试。例如,https://github.com/willf/bloom在github上授予了一些明星奖。这个特定的实现使用murmur3进行散列的散列和bitset,因此可以比map更有效。