目录
实例1
type Fts_message_table_content_nomal struct {
Docid int64 `xorm:"docid"`
C0CreateTime int64 `xorm:"c0CreateTime"`
C1MesLocalID int64 `xorm:"c1MesLocalID"`
C2Message string `xorm:"c2Message"`
C3reservedInt string `xorm:"c3reservedInt"`
C4reservedText string `xorm:"c4reservedText"`
C5usernameid int64 `xorm:"c5usernameid"`
C6CONSTRAINT string `xorm:"c6CONSTRAINT"`
}
type Message_contents_normal []Fts_message_table_content_nomal
func removeDuplicate(personList Message_contents_normal) Message_contents_normal {
resultMap := map[string]bool{}
for _, v := range personList {
data, _ := json.Marshal(v)
resultMap[string(data)] = true
}
result := Message_contents_normal{}
for k := range resultMap {
var t Fts_message_table_content_nomal
json.Unmarshal([]byte(k), &t)
result = append(result, t)
}
return result
}
实例2
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()
方法的返回值)
函数返回值的类型是空接口,所以拿到返回值后要进行类型断言才能使用。