Arrays 在Go切片或数组中查找唯一项
我是个新手,现在真的很困惑 假设我有一个坐标列表,在这个坐标列表中有一些双精度的。我一辈子都想不出如何列出一份独特的清单。通常在Python中,我可以使用集合和其他内置项“作弊”。没有那么多人去Arrays 在Go切片或数组中查找唯一项,arrays,go,set,unique,slice,Arrays,Go,Set,Unique,Slice,我是个新手,现在真的很困惑 假设我有一个坐标列表,在这个坐标列表中有一些双精度的。我一辈子都想不出如何列出一份独特的清单。通常在Python中,我可以使用集合和其他内置项“作弊”。没有那么多人去 package main import ( "fmt" "reflect" ) type visit struct { x, y int } func main() { var visited []visit var unique []visit
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)
}
您的代码中有多个错误。最严重的是,由于您将访问的
片段的每个特定元素与唯一的元素的所有进行比较,因此如果唯一的至少包含一个不同的元素,您将最终追加该元素。向前看,如果unique
中有更多的元素,并且由于内部for
循环没有“中断”而不同,那么您将多次追加它。这不是您想要的,您想要附加的元素等于unique
的none
还请注意,如果Go中的struct
的每个字段都是可比较的,那么它是可比较的。由于您的visit
结构只包含2个int
字段,因此它是可比较的,因此您可以使用=
操作符简单地比较visit
类型的值,而无需使用丑陋的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确实没有内置的集合类型,但您可以轻松地将map[visit]bool
作为集合使用。这样,事情就变得非常简单了!请注意,visit
可以用作地图中的键,因为它具有可比性(见上文)
输出(在上尝试):
唯一的“列表”是地图中的键列表
如果要将唯一的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)
输出(如预期,请在上尝试):
请注意,此索引表达式:m[v]
的计算结果为true
,如果v
已在映射中(作为键,true
是我们存储在映射中的值)。如果v
尚未在映射中,则m[v]
为类型bool
生成值类型的零值,该值类型为false
,正确地告知值v
尚未在映射中。见:
对于M
:
…如果映射为nil
或不包含此类条目,a[x]
是M
我想你可以多参观几次。
像这样的
visited := make(map[visit]Boolean)
然后您可以设置访问的值
visited[visit]=true
最后,您可以通过此代码获取所有访问过的位置
for k, _ := range visited {
unique = append(unique, k)
}
我想你可以借助地图来解决这个难题
非常感谢您的指导、反馈和修改。就像我说的,我是新手。再次感谢!如果希望列表只包含唯一的条目,通常可以执行类似于map[string]struct{}{}
的操作。空结构不会占用任何内存。
[{1 100} {2 2} {1 1}]
visited := make(map[visit]Boolean)
visited[visit]=true
for k, _ := range visited {
unique = append(unique, k)
}
package main
import (
"fmt"
)
type visit struct {
x, y int
}
func main() {
var visited []visit
var unique []visit
uniqueMap := map[visit]int{}
visited = append(visited, visit{1, 100})
visited = append(visited, visit{2, 2})
visited = append(visited, visit{1, 100})
visited = append(visited, visit{1, 1})
for _, v := range visited {
if _, exist := uniqueMap[v]; !exist {
uniqueMap[v] = 1
unique = append(unique, v)
} else {
uniqueMap[v]++
}
}
fmt.Printf("Uniques: %v\nMaps:%v\n", unique, uniqueMap)
}