在Go中删除片断重复内容的方法

83 阅读1分钟

我们之前的一个例子中,我们创建了一个函数,可以从Go中的一个片断中删除重复的值。然而,这个函数需要在每次片断的类型不同时重新实现。因此,如果我们有[]int[]string 分片,而我们想删除其中的重复值,到目前为止,我们需要两个函数:uniqueString()uniqueInt() 。但随着Go 1.18中泛型函数的发布,这不再是必要的了。我们可以编写一个单一的函数,它可以在任何值满足 comparable约束的任何片断。

package main

import "fmt"

func unique[T comparable](s []T) []T {
    inResult := make(map[T]bool)
    var result []T
    for _, str := range s {
        if _, ok := inResult[str]; !ok {
            inResult[str] = true
            result = append(result, str)
        }
    }
    return result
}

type FruitRank struct {
    Fruit string
    Rank  uint64
}

func main() {
    fmt.Println(unique([]string{"abc", "cde", "efg", "efg", "abc", "cde"}))
    fmt.Println(unique([]int{1, 1, 2, 2, 3, 3, 4}))

    fruits := []FruitRank{
        {
            Fruit: "Strawberry",
            Rank:  1,
        },
        {
            Fruit: "Raspberry",
            Rank:  2,
        },
        {
            Fruit: "Blueberry",
            Rank:  3,
        },
        {
            Fruit: "Blueberry",
            Rank:  3,
        },
        {
            Fruit: "Strawberry",
            Rank:  1,
        },
    }
    fmt.Println(unique(fruits))
}

输出

[abc cde efg]
[1 2 3 4]
[{Strawberry 1} {Raspberry 2} {Blueberry 3}]

该函数与非泛型版本的区别仅在于它使用了一个类型参数T ,并带有 comparable约束。这是一个内置的约束,描述了任何可以使用==!= 操作符的类型。

我们创建的unique() 函数是一个通用的重复删除函数,正如你在例子的输出中所看到的,它对任何comparable 分片,如[]string,[]int, 或定义的struct 分片都有效。