golang struct 切片数组去重

目录

实例1

实例2

适配多个切片类型


实例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值类型为空structmap,等效于使用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值类型为空structmap。key的值是切片元素的字符串表现形式(类型的String()方法的返回值)

函数返回值的类型是空接口,所以拿到返回值后要进行类型断言才能使用。

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值