golang为什么我们没有设置数据结构

anj*_*anb 100 set go data-structures

我正在尝试解决"去编程语言"练习#1.4,这需要我有一套.我可以创建一个集合类型,但为什么语言没有附带?go,来自谷歌,guava也来自哪里,为什么语言设计师不选择添加对基础数据结构的支持?为什么强迫你的用户创建自己的实现为一个基本的集合?

Vat*_*ine 70

部分原因是因为Go没有泛型(所以你需要为每种类型设置一种类型,或者反复使用反射,这是相当低效的).

部分地,因为如果你只需要"添加/删除单个元素到一个集合"和"相对节省空间",你可以简单地通过使用a map[yourtype]bool(并为集合中的true任何元素设置值)来获得相当一部分)或者,为了提高空间效率,您可以使用空结构作为值并使用它_, present = the_setoid[key]来检查是否存在.

  • golang 问题的通常答案是:“当你只需几行就能重写一个功能时,为什么要提供它?”。这就是为什么在 python(或许多其他语言)中可以用 3 行显式代码完成的事情在 go 中需要 50 多行晦涩难懂的代码。这是我讨厌阅读 Go 代码的原因之一(以及单字母变量)。它太长了,毫无用处,只是用 for 循环完成了应该由一个清晰、高效且经过良好测试的正确命名函数完成的工作。Go“精神”只是以可疑的理由抛弃了 50 年的良好软件工程实践。 (84认同)
  • 因此,如果它没有泛型,那么"通用"地图是如何实现的呢? (27认同)
  • 请注意,如果要保存字节,可以使用`map [T] struct {}`而不是`map [T] bool`. (24认同)
  • 鉴于泛型将在 1.18 中引入 Go(https://bitfieldconsulting.com/golang/generics#:~:text=Know%20Go%3F,to%20coincide%20with%20Go%201.18。)这里列出的原因可能会变成过时的。 (5认同)
  • 看看https://emersion.fr/blog/2017/sets-in-go/ (4认同)
  • @FerminSilva 它是由编译器完成的,使用开发人员无法直接访问的方法。 (2认同)
  • 现在 Golang 1.19 版本中是否有 Set DS 的通用实现? (2认同)

Sal*_*ali 52

一个原因是从地图创建集合很容易:

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

联盟

s_union := map[int]bool{}
for k, _ := range s1{
    s_union[k] = true
}
for k, _ := range s2{
    s_union[k] = true
}
Run Code Online (Sandbox Code Playgroud)

路口

s_intersection := map[int]bool{}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}
Run Code Online (Sandbox Code Playgroud)

实现所有其他设置操作并不是那么难.

  • 很高兴重新发明轮子 (50认同)
  • 使用`map [int] struct {}`而不是`bool`更为理想,因为空结构在内存中占用0个字节.我最近写了这个https://gist.github.com/bgadrian/cb8b9344d9c66571ef331a14eb7a2e80的要点 (21认同)
  • 既不容易也不直观。这不是一个集合,它只是一个行为类似于集合的代码模式。它不是一个集合,因为它不存储数据,也不提供集合那样的操作。正确答案是GO没有这个功能。有办法做某事并不意味着有理由不这样做。 (9认同)
  • 检查是否存在只是索引地图.因为如果它不在其中,零值(即"false")将正确地告诉它.不需要逗号成语来进行测试. (8认同)
  • 那不是那么容易。这些天来,只需要在需要使用Set的任何地方编写该代码就对我来说很荒谬。收款支持应以任何语言提供。认为更好的答案是Go尚未成熟。我相信将会有足够的图书馆来对此进行介绍。 (6认同)
  • Golang 哲学:让我们抛弃讨厌的计算机科学抽象概念,每次都从第一原理重新编码一切。 (5认同)
  • 即使它很简单(我并不是说这是真的),但这根本不是不提供它的理由。 (4认同)
  • Golang - “重新发明轮子。每一次。” © (3认同)
  • 交集的实现看起来像差异. (2认同)
  • 我对答案不太满意,它不存在,因为有一个解决方法。 (2认同)
  • 我认为,关于实施的如此多的讨论这一事实正好说明了为什么需要设置支持。我还认为,如果争论是“你可以使用其他原语来实现它”,那么为什么 Go 甚至有一个标准库?当你可以只写入标准输出时,“log”有什么意义?逻辑似乎不一致。 (2认同)

0x4*_*D53 9

就像 Vatine 写道:由于 go 缺少泛型,因此它必须成为语言的一部分,而不是标准库。为此,您将不得不使用关键字集、联合、交集、差异、子集来污染语言......

另一个原因是,根本不清楚集合的“正确”实现是什么:

  1. 有一种功能方法:

    func IsInEvenNumbers(n int) bool {
        if n % 2 == 0 {
            return true
        }
       return false
    }
    
    Run Code Online (Sandbox Code Playgroud)

这是一组所有偶数整数。它具有非常高效的查找和并集,相交、差异和子集可以通过功能组合轻松完成。

  1. 或者你做一个像达利展示的类似的方法。

地图没有这个问题,因为你存储了一些与值相关的东西。

  • 事实上,有多种方法可以实现一个集合并没有阻止许多其他语言提供它们。 (19认同)
  • 我知道这已经有 5 年历史了,但是“用关键字 set、union、intersection、difference、subset 污染了语言”,真的吗?除了“set”之外,其余都是对集合的操作,因此它们是函数。 (12认同)
  • 为了处理内置集合,Pascal 重载了一堆二元(双参数)运算符:`+` 表示并集,`-` 表示差,`*` 表示交集,`<=` 表示子集,`>=` 表示超集,`=` 表示相等,`<>` 表示不等,`in` 表示成员资格。所以在 Go 中,它只是一个新的关键字——`in`。另一方面,Pascal 的内置集合仅适用于“序数”——也就是说,任何具有某种大小整数值的底层表示的类型。 (2认同)
  • 有什么理由不简单地返回 `n % 2 == 0`? (2认同)

Wil*_*ald 5

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