68
Go如何对数组切片进行去重
source link: https://www.tuicool.com/articles/VF3yiy2
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Go标准库本身没有提供一个去除slice中重复元素的函数,需要自己去实现。下面提供一种实现思路,如果有更好的实现方法欢迎留言讨论。
package main import ( "fmt" ) func main() { s := []string{"hello", "world", "hello", "golang", "hello", "ruby", "php", "java"} fmt.Println(removeDuplicateElement(s)) //output: hello world golang ruby php java } func removeDuplicateElement(languages []string) []string { result := make([]string, 0, len(languages)) temp := map[string]struct{}{} for _, item := range languages { if _, ok := temp[item]; !ok { temp[item] = struct{}{} result = append(result, item) } } return result }
解释
-
removeDuplicateElement
函数总共初始化两个变量,一个长度为0的slice
,一个空map
。由于slice
传参是按引用传递,没有创建占用额外的内存空间。 -
map[string]struct{}{}
创建了一个key类型为String值类型为空struct
的map
,等效于使用make(map[string]struct{})
-
空
struct
不占内存空间,使用它来实现我们的函数空间复杂度是最低的。
适配多个切片类型
上面的去除重复元素的函数,只能处理字符串切片对于其他类型的切片就不行了。如果不想针对每种类型的切片都写一个去重函数的话可以使用Go的type-switch自己写一个可以处理多个切片类型的函数。下面是我写的一个实现:
package common import ( "fmt" ) type sliceError struct { msg string } func (e *sliceError) Error() string { return e.msg } func Errorf(format string, args ...interface{}) error { msg := fmt.Sprintf(format, args...) return &sliceError{msg} } func removeDuplicateElement1(originals interface{}) (interface{}, error) { temp := map[string]struct{}{} switch slice := originals.(type) { case []string: result := make([]string, 0, len(originals.([]string))) for _, item := range slice { key := fmt.Sprint(item) if _, ok := temp[key]; !ok { temp[key] = struct{}{} result = append(result, item) } } return result, nil case []int64: result := make([]int64, 0, len(originals.([]int64))) for _, item := range slice { key := fmt.Sprint(item) if _, ok := temp[key]; !ok { temp[key] = struct{}{} result = append(result, item) } } return result, nil default: err := Errorf("Unknown type: %T", slice) return nil, err } }
- 函数接收一个空接口类型的参数,然后使用类型选择进入相应的分支进行处理。这里可以根据需求添加函数需支持的切片类型的处理程序。
-
每个分支里同样创建了一个key类型为string值类型为空
struct
的map
。key的值是切片元素的字符串表现形式(类型的String()
方法的返回值) - 函数返回值的类型是空接口,所以拿到返回值后要进行类型断言才能使用。
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK