我们可以在go中编写通用数组/片重复数据删除吗?

时间:2014-04-24 17:22:45

标签: go deduplication

有没有办法在go中编写通用数组/切片重复数据删除,对于[]int,我们可以使用(来自http://rosettacode.org/wiki/Remove_duplicate_elements#Go):

func uniq(list []int) []int {
  unique_set := make(map[int] bool, len(list))
  for _, x := range list {
     unique_set[x] = true
   }
  result := make([]int, len(unique_set))
  i := 0
  for x := range unique_set {
     result[i] = x
    i++
  }
  return result
}

但有没有办法扩展它以支持任何数组?签名如:

func deduplicate(a []interface{}) []interface{}

我知道您可以使用该签名编写该功能,但是您无法在[]int上实际使用该功能,您需要创建[]interface{}来放置{{1}的所有内容进入它,将其传递给函数然后将其返回并放入[]int并遍历这个新数组并将所有内容放入新的[]interface{}中。

我的问题是,还有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

虽然VonC的答案可能与你真正想要的最接近,但是在没有gen的情况下在本机Go中做到这一点的唯一真正方法是定义一个接口

type IDList interface {
   // Returns the id of the element at i
   ID(i int) int

   // Returns the element
   // with the given id
   GetByID(id int) interface{}

   Len() int

   // Adds the element to the list
   Insert(interface{})
}

// Puts the deduplicated list in dst
func Deduplicate(dst, list IDList) {
    intList := make([]int, list.Len())
    for i := range intList {
        intList[i] = list.ID(i)
    }

    uniques := uniq(intList)
    for _,el := range uniques {
        dst.Insert(list.GetByID(el))
    }
}

uniq是OP的功能。

这只是一个可能的例子,并且可能有更好的例子,但通常将每个元素映射到唯一的“== able”ID,并且构建新列表或基于ID的重复数据删除进行剔除可能是最直观的方式。

另一种解决方案是接收[]IDer IDer接口只有ID() int的{​​{1}}。但是,这意味着用户代码必须创建[] IDer列表并将所有元素复制到该列表中,这有点难看。用户将列表包装为ID列表而不是复制更清晰,但无论如何都是类似的工作量。

答案 1 :(得分:2)

我在Go中实现的唯一方法是使用clipperhouse/gen项目,

  

gen试图为Go带来一些类似于泛型的功能,其中一些灵感来自C#的Linq和JavaScript的下划线库

请参阅this test

// Distinct returns a new Thing1s slice whose elements are unique. See: http://clipperhouse.github.io/gen/#Distinct
func (rcv Thing1s) Distinct() (result Thing1s) {
    appended := make(map[Thing1]bool)
    for _, v := range rcv {
        if !appended[v] {
            result = append(result, v)
            appended[v] = true
        }
    }
    return result
}

,如clipperhouse.github.io/gen/中所述:

  

gen 使用命令行在开发时为您的类型生成代码

     

gen不是导入;生成的源成为项目的一部分,不会产生外部依赖。

答案 2 :(得分:1)

您可以通过界面做一些与此相近的事情。定义一个界面,说" DeDupable"需要一个func,比如UniqId()[] byte,然后你就可以用来删除重复了。你的uniq func会带一个[] DeDupable并继续工作