2023-11-10 05:01:49

包含片的方法

是否有类似于Go中的slice.contains(object)方法,而无需在slice中逐个搜索每个元素?


当前回答

如果切片已排序,则排序包中实现了二进制搜索。

其他回答

在Go 1.18+中,我们可以使用泛型。

func Contains[T comparable](s []T, e T) bool {
    for _, v := range s {
        if v == e {
            return true
        }
    }
    return false
}

不确定这里是否需要泛型。你只需要为你想要的行为订立契约。如果您想让自己的对象在集合中表现自己,那么在其他语言中,通过重写Equals()和GetHashCode(),您必须做的事情不亚于下面所做的事情。

type Identifiable interface{
    GetIdentity() string
}

func IsIdentical(this Identifiable, that Identifiable) bool{
    return (&this == &that) || (this.GetIdentity() == that.GetIdentity())
}

func contains(s []Identifiable, e Identifiable) bool {
    for _, a := range s {
        if IsIdentical(a,e) {
            return true
        }
    }
    return false
}

你可以使用reflect包来迭代一个具体类型为slice的接口:

func HasElem(s interface{}, elem interface{}) bool {
    arrV := reflect.ValueOf(s)

    if arrV.Kind() == reflect.Slice {
        for i := 0; i < arrV.Len(); i++ {

            // XXX - panics if slice element points to an unexported struct field
            // see https://golang.org/pkg/reflect/#Value.Interface
            if arrV.Index(i).Interface() == elem {
                return true
            }
        }
    }

    return false
}

https://play.golang.org/p/jL5UD7yCNq

如果使用地图根据钥匙查找物品是不可行的,你可以考虑使用goderived工具。goderived生成包含方法的特定于类型的实现,使您的代码既可读又高效。

例子;

type Foo struct {
    Field1 string
    Field2 int
} 

func Test(m Foo) bool {
     var allItems []Foo
     return deriveContainsFoo(allItems, m)
}

生成派生econtainsfoo方法:

使用go get -u github.com/awalterschulze/goderive安装goderived 运行goderived。/…在工作区文件夹中

这个方法将为衍生的包含生成:

func deriveContainsFoo(list []Foo, item Foo) bool {
    for _, v := range list {
        if v == item {
            return true
        }
    }
    return false
}

goderived还支持很多其他有用的辅助方法,可以在go中应用函数式编程风格。

如果切片已排序,则排序包中实现了二进制搜索。