英文:
Go equivalent to std::set?
问题
在Go语言中,与std::set相对应的是什么?请注意,只有唯一性是重要的,我不关心顺序。
我考虑过使用虚拟类型,比如map[string]bool(其中bool是虚拟类型),然而在Go语言中,我经常发现需要提供一个不需要的类型,比如将通道用作信号量,在这种情况下。我是否遗漏了Go语言中的某些惯用方法?
英文:
What would be the equivalent in Go to a std::set? Note that only uniqueness is important, I don't care about ordering.
I've considered using dummy type, such as map[string]bool (where bool is the dummy), however often I find in Go I need to provide a type where one is not required, such as a channel used as a semaphore, and this case. Am I missing something idiomatic to Go?
答案1
得分: 6
在像Perl这样没有集合的语言中,使用带有虚拟值的映射作为集合是常见的做法。我认为这是一种在Go中获取集合的可接受方式,除非你想自己实现它或使用一些第三方实现。当然,你的数据类型必须是允许作为映射键的类型,即不能是结构体、数组或切片。
英文:
Using a map with dummy values as a set is common practice in languages like Perl, which do not have sets. I think it is an acceptable way to get sets in Go, unless you want to implement it yourself or use some third-party implementation. Of course, your datatype has to be one that is allowed as the key in a map, i.e. not struct, array, or slice.
答案2
得分: 3
使用map[string]bool是完全可以的。
还有一些更高级的库可以处理集合,例如:https://github.com/pwil3058/gosets
但我仍然会坚持使用简单的map,它更符合惯用法并且更简单,这总是好的。
英文:
Using map[string]bool is perfectly fine.
There are also some more fancy libraries to handle sets, see for example: https://github.com/pwil3058/gosets
But I would still stick with a simple map, it is more idiomatic and simpler, which is always good.
答案3
得分: 2
使用map[string]bool(将true作为虚拟值)或map[string]struct{}作为集合被认为是Go语言中的惯用方式。它们各自有优缺点。
假设:
b := make(map[string]bool)
s := make(map[string]struct{})
-
使用
b更容易检查集合是否包含元素:if b["x"] { // b包含"x" } if _, ok := s["x"]; ok { // s包含"x" } -
除非你能保证
b不包含任何false值,否则使用s更容易遍历元素:for e, v := range b { if v { // e是b的元素 } } for e := range s { // e是s的元素 } -
s比b更节省内存。
作为替代方案,你可以使用开源库。例如:
github.com/soroushj/menge实现了所有基本类型的集合。k8s.io/apimachinery/pkg/util/sets实现了整数(byte、int、int32、int64)和字符串的集合。
当然,目前在Go中无法实现通用集合。但是随着计划中将泛型引入Go的版本更新,将来将有可能实现(最早在1.17版本之后)。
英文:
Using map[string]bool (with true as the dummy value) or map[string]struct{} as a set is considered idiomatic Go. Each of them has its own pros and cons.
Assume:
b := make(map[string]bool)
s := make(map[string]struct{})
-
Checking whether a set has an element is easier with
b:if b["x"] { // b has "x" } if _, ok := s["x"]; ok { // s has "x" } -
Unless you can guarantee that
bdoes not have anyfalsevalues, iterating over the elements is easier withs:for e, v := range b { if v { // e is an element of b } } for e := range s { // e is an element of s } -
sis more memory-efficient thanb.
As an alternative, you can use an open-source library. For instance:
github.com/soroushj/mengeimplements sets of all basic types.k8s.io/apimachinery/pkg/util/setsimplements sets of integers (byte,int,int32,int64) and strings.
Of course, currently, it's not possible to implement generic sets in Go. But with the planned addition of generics to Go, it will be possible in a later version (no earlier than 1.17).
答案4
得分: 0
如果有人需要一个int的集合,可以使用以下代码:
package main
import "golang.org/x/tools/container/intsets"
func main() {
var (
a intsets.Sparse
b bool
)
b = a.Insert(9)
println(b) // true
b = a.Insert(9)
println(b) // false
}
https://pkg.go.dev/golang.org/x/tools/container/intsets
英文:
If anyone need a set of int, you can use this:
package main
import "golang.org/x/tools/container/intsets"
func main() {
var (
a intsets.Sparse
b bool
)
b = a.Insert(9)
println(b) // true
b = a.Insert(9)
println(b) // false
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论