在Go Slice或数组中查找唯一项

我很新,我现在真的非常困惑。

假设我有一个坐标列表,并且说我在此坐标列表中有一些双打。我一辈子都无法弄清楚如何制作一份独特的清单。通常,在Python中,我可以“欺骗”集合和其他内置函数。在Go中没有那么多。

package main

import (

"fmt"

"reflect"

)

type visit struct {

x, y int

}

func main() {

var visited []visit

var unique []visit

visited = append(visited, visit{1, 100})

visited = append(visited, visit{2, 2})

visited = append(visited, visit{1, 100})

visited = append(visited, visit{1, 1})

unique = append(unique, visit{1, 1})

fmt.Println(unique)

// Go through the visits and find the unique elements

for _, v := range visited {

for _, u := range unique {

fmt.Printf("Here's unique: %v\n", unique)

fmt.Printf("Comparing %v to %v is %v\n", v, u, reflect.DeepEqual(v, u))

if reflect.DeepEqual(v, u) {

fmt.Println("Skip")

} else {

unique = append(unique, v)

}

}

}

fmt.Println(unique)

}

[Run it on Playground](https://play.golang.org/p/7lYjfSaBP0)

回答:

您的代码中存在多个错误。最严重的是,由于您要将visited切片的每个特定元素与的

元素进行比较unique,因此如果unique包含至少一个不同的元素,最终将附加它。而且,如果由于unique内部for循环不会“中断”

而有更多不同的元素,您将最终多次追加它。这是不是你想要的,你要追加相等于元素 的unique

还要注意,struct如果Go中的每个字段都是可比较的,则a

in可比较。由于您的visit结构仅包含2个int字段,因此具有可比性,因此您可以visit简单地将type的值与==运算符进行比较,而不必太丑陋reflect.DeepEqual()。请参见规格:比较运算符:

如果结构的所有字段都是可比较的,则它们的值是可比较的。如果两个结构值对应的非空白字段相等,则它们相等。

这是适用您逻辑的简化正确版本:

visited := []visit{

visit{1, 100},

visit{2, 2},

visit{1, 100},

visit{1, 1},

}

var unique []visit

for _, v := range visited {

skip := false

for _, u := range unique {

if v == u {

skip = true

break

}

}

if !skip {

unique = append(unique, v)

}

}

fmt.Println(unique)

输出(在Go Playground上尝试):

[{1 100} {2 2} {1 1}]

另类

确实,Go没有内置的集合类型,但是您可以map[visit]bool轻松地将其用作集合。这样,它变得非常简单!请注意,visit由于它具有可比性,因此可以用作地图中的键(请参见上文)。

visited := []visit{

visit{1, 100},

visit{2, 2},

visit{1, 100},

visit{1, 1},

}

unique := map[visit]bool{}

for _, v := range visited {

unique[v] = true

}

fmt.Println(unique)

输出(在Go Playground上尝试):

map[{2 2}:true {1 1}:true {1 100}:true]

唯一的“列表”是地图中键的列表。

如果要将唯一visit值用作切片,请参见以下变体:

var unique []visit

m := map[visit]bool{}

for _, v := range visited {

if !m[v] {

m[v] = true

unique = append(unique, v)

}

}

fmt.Println(unique)

输出(如预期的那样,在Go Playground上尝试):

[{1 100} {2 2} {1 1}]

请注意,此索引表达式:m[v]计算true是否v在地图中(作为键,true是我们存储在地图中的值)。如果v还没有在地图上,m[v]得出这是值类型的零值false的类型bool,正确地告诉该值v还没有在地图上。请参见规格:索引表达式:

对于地图类型 M

…如果地图nil包含或不包含此类条目,a[x]则是的值类型的零值M

以上是 在Go Slice或数组中查找唯一项 的全部内容, 来源链接: utcz.com/qa/397324.html

回到顶部