2

有没有办法在 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{}将所有内容[]int放入其中,将其传递给函数然后将其取回并将其放入 a[]interface{}和遍历这个新数组并将所有内容放入一个新的[]int.

我的问题是,有没有更好的方法来做到这一点?

4

3 回答 3

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 列表而不是复制更简洁,但无论哪种方式,工作量都差不多。IDerID() int

于 2014-04-24T22:56:49.730 回答
2

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

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

看到这个测试

// 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 不是进口商品;生成的源代码成为您项目的一部分,并且没有外部依赖项。

于 2014-04-24T17:38:50.957 回答
1

您可以通过界面做一些接近此的事情。定义一个接口,比如“DeDupable”,需要一个函数,比如 UniqId() []byte,然后您可以使用它来删除 dups。并且您的 uniq func 将采用 []DeDupable 并对其进行处理

于 2014-04-24T18:19:51.840 回答