为什么 Golang 没有集合数据结构?

huangapple go评论128阅读模式
英文:

golang why don't we have a set datastructure

问题

我正在尝试解决《Go编程语言》的练习1.4,这个练习要求我使用一个集合。我可以创建一个集合类型,但为什么语言本身没有提供一个集合类型呢?Go语言来自Google,而Guava也是由Google开发的,为什么语言设计者没有选择为基本数据结构添加支持呢?为什么要强迫用户自己实现一个如此基本的集合类型呢?

英文:

I'm trying to solve "The go programming lanaguage" exercise #1.4 which requires me to have a set. I can create a set type but why doesn't the language come with one ? go, having come from google, where guava also originated, why didn't the language designers opt for adding support for fundamental data structures ? why force your users to create their own implementations for something so basic as a set ?

答案1

得分: 154

一个原因是从映射创建集合很容易:

s := map[int]bool{5: true, 2: true}
_, ok := s[6] // 检查元素是否存在
s[8] = true // 添加元素
delete(s, 2) // 删除元素

并集

s_union := map[int]bool{}
for k, _ := range s1{
	s_union[k] = true
}
for k, _ := range s2{
	s_union[k] = true
}

交集

s_intersection := map[int]bool{}
if len(s1) > len(s2) {
  s1, s2 = s2, s1 // 最好遍历较短的集合
}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}

实现其他所有集合操作并不是真的很难。

英文:

One reason is that it is easy to create a set from map:

s := map[int]bool{5: true, 2: true}
_, ok := s[6] // check for existence
s[8] = true // add element 
delete(s, 2) // remove element

Union

s_union := map[int]bool{}
for k, _ := range s1{
	s_union[k] = true
}
for k, _ := range s2{
	s_union[k] = true
}

Intersection

s_intersection := map[int]bool{}
if len(s1) > len(s2) {
  s1, s2 = s2, s1 // better to iterate over a shorter set
}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}

It is not really that hard to implement all other set operations.

答案2

得分: 126

部分原因是因为Go语言没有泛型(所以你需要为每种类型都需要一个集合类型,或者退而求其次使用反射,但这样效率相对较低)。

另一部分原因是,如果你只需要“向集合中添加/删除单个元素”和“相对空间高效”,你可以通过使用map[yourtype]bool来实现这一点(并将集合中的元素的值设置为true),或者为了更高的空间效率,你可以使用一个空结构体作为值,并使用_, present = the_setoid[key]来检查是否存在。

英文:

Partly, because Go doesn't have generics (so you would need one set-type for every type, or fall back on reflection, which is rather inefficient).

Partly, because if all you need is "add/remove individual elements to a set" and "relatively space-efficient", you can get a fair bit of that simply by using a map[yourtype]bool (and set the value to true for any element in the set) or, for more space efficiency, you can use an empty struct as the value and use _, present = the_setoid[key] to check for presence.

答案3

得分: 5

另一种可能性是使用位集,有至少一个可以使用,或者您可以使用内置的big包。在这种情况下,基本上您需要定义一种将您的对象转换为索引的方法。

英文:

Another possibility is to use bit sets, for which there is at least one package or you can use the built-in big package. In this case, basically you need to define a way to convert your object to an index.

答案4

得分: 4

像Vatine写的那样:由于Go语言缺乏泛型,集合必须成为语言的一部分,而不是标准库的一部分。为此,你需要在语言中引入关键字set、union、intersection、difference、subset等。

另一个原因是,对于集合的“正确”实现并不明确:

  1. 有一种函数式的方法:

     func IsInEvenNumbers(n int) bool {
         if n % 2 == 0 {
             return true
         }
        return false
     }
    

这是一个包含所有偶数的集合。它具有非常高效的查找功能,并且可以通过函数组合轻松地进行并集、交集、差集和子集操作。

  1. 或者你可以像Dali展示的那样使用类似哈希表的方法。

使用映射(map)就不会有这个问题,因为你可以将某个值与键关联起来存储。

英文:

Like Vatine wrote: Since go lacks generics it would have to be part of the language and not the standard library. For that you would then have to pollute the language with keywords set, union, intersection, difference, subset...

The other reason is, that it's not clear at all what the "right" implementation of a set is:

  1. There is a functional approach:

     func IsInEvenNumbers(n int) bool {
         if n % 2 == 0 {
             return true
         }
        return false
     }
    

This is a set of all even ints. It has a very efficient lookup and union, intersect, difference and subset can easily be done by functional composition.

  1. Or you do a has-like approach like Dali showed.

A map does not have that problem, since you store something associated with the value.

huangapple
  • 本文由 发表于 2015年12月1日 19:09:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/34018908.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定