我很新,我现在真的很困惑。
假设我有一个坐标列表,让我说这个坐标列表中有一些双打。我不能为我的生活弄清楚如何制作一个独特的清单。通常在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)
}
答案 0 :(得分:8)
您的代码中存在多个错误。最严重的是,因为您要将visited
切片的每个特定元素与unique
元素的所有进行比较,所以如果{{1},您最终会附加它包含至少一个不同的。如果unique
中有更多元素因内部unique
循环没有“中断”而有所不同,那么最后会多次追加它。这不是你想要的,你想要追加等于for
的无的元素。
另请注意,如果每个字段都具有可比性,则Go中的unique
具有可比性。由于您的struct
结构只包含2个visit
字段,因此它具有可比性,因此您可以简单地将int
类型的值与visit
运算符进行比较,而不需要那么丑=
1}}。见Spec: Comparison operators:
如果所有字段都具有可比性,则结构值具有可比性。如果相应的非blank字段相等,则两个struct值相等。
这是一个适用于您的逻辑的简化版本:
reflect.DeepEqual()
输出(在Go Playground上尝试):
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确实没有内置的集合类型,但您可以轻松地使用[{1 100} {2 2} {1 1}]
作为集合。有了它,它变得非常简单!请注意,map[visit]bool
可以用作地图中的关键字,因为它具有可比性(见上文)。
visit
输出(在Go Playground上尝试):
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)
唯一的“列表”是地图中的键列表。
如果您希望将唯一map[{2 2}:true {1 1}:true {1 100}:true]
值作为切片,请参阅以下变体:
visit
输出(按预期,在Go Playground上尝试):
var unique []visit
m := map[visit]bool{}
for _, v := range visited {
if !m[v] {
m[v] = true
unique = append(unique, v)
}
}
fmt.Println(unique)
请注意,如果[{1 100} {2 2} {1 1}]
已经在地图中,则此索引表达式m[v]
的结果为true
(作为关键字,v
是我们存储在地图中的值)。如果地图中尚未显示true
,则v
会为类型m[v]
生成false
值类型的零值,并正确告知值{{1}尚未出现在地图中。见Spec: Index expressions:
适用于map type
bool
:...如果地图为
v
或不包含此类条目,M
为值nil
的{{3}}
答案 1 :(得分:2)
我认为您可以进行map次访问。 像这样的东西
visited := make(map[visit]Boolean)
比您可以设置被访问的值。
visited[visit]=true
最后,您可以通过此代码
获取所有访问过的位置for k, _ := range visited {
unique = append(unique, k)
}
答案 2 :(得分:1)
我认为您可以使用Map的帮助来解决这个难题
https://play.golang.org/p/b7JtHYQ3N8
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)
}