我是新手,现在我真的、真的很困惑。
假设我有一个坐标列表,假设我在这个坐标列表中有一些 double 。我这辈子都想不出如何制作一份独特的 list 。通常在 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)
}
最佳答案
您的代码中存在多个错误。最严重的是,由于您将 visited
slice 的每个特定元素与 unique
的所有元素进行比较,您最终会如果 unique
至少包含一个不同的,则附加它。继续前进,如果 unique
中有更多元素,您最终将多次附加它,因为您的内部 for
循环不会“中断”。这不是您想要的,您想要附加等于 unique
的 none 的元素。
另请注意,如果每个字段都是可比较的,则 Go 中的 struct
也是可比较的。由于您的 visit
结构仅包含 2 个 int
字段,因此它具有可比性,因此您可以简单地使用 = 比较
运算符,不需要那个丑陋的 visit
类型的值=reflect.DeepEqual()
。参见 Spec: Comparison operators :
Struct values are comparable if all their fields are comparable. Two struct values are equal if their corresponding non-blank fields are equal.
这是应用您的逻辑的简化、正确的版本:
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
可以用作 map 中的键,因为它具有可比性(见上文)。
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
值作为一个 slice ,请参阅以下变体:
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}]
请注意,如果 v
已经在映射中(作为键,true
是我们存储在 map 中的值)。如果 v
尚未在映射中,则 m[v]
生成值类型的零值,对于 类型为
,正确地表明值 false
>boolv
还不在 map 中。参见 Spec: Index expressions :
For a of map type
M
:...if the map is
nil
or does not contain such an entry,a[x]
is the zero value for the value type ofM
关于arrays - 在 Go slice 或数组中查找唯一项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34111476/