英文:
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
b
does not have anyfalse
values, 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 }
-
s
is more memory-efficient thanb
.
As an alternative, you can use an open-source library. For instance:
github.com/soroushj/menge
implements sets of all basic types.k8s.io/apimachinery/pkg/util/sets
implements 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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论