有没有办法在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{}
中。
我的问题是,还有更好的方法吗?
答案 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并继续工作