【问题标题】:Go equivalent to std::set?相当于 std::set?
【发布时间】:2011-05-16 11:11:20
【问题描述】:

在转到std::set 中的等价物是什么?请注意,只有唯一性很重要,我不关心排序。

我考虑过使用虚拟类型,例如 map[string]bool(其中 bool 是虚拟类型),但是我经常发现在 Go 中我需要提供一个不需要的类型,例如用作一个信号量,和这种情况。我错过了一些惯用的 Go 语言吗?

【问题讨论】:

    标签: containers go


    【解决方案1】:

    在没有集合的 Perl 等语言中,将具有虚拟值的映射用作集合是常见的做法。我认为这是在 Go 中获取集合的一种可接受的方式,除非您想自己实现它或使用一些第三方实现。当然,您的数据类型必须是允许作为映射中键的类型,即不能是结构、数组或切片。

    【讨论】:

      【解决方案2】:

      使用map[string]bool 完全没问题。

      还有一些更花哨的库来处理集合,例如:https://github.com/pwil3058/gosets

      但我还是会坚持使用简单的地图,它更惯用、更简单,这总是好的。

      【讨论】:

      • 链接已损坏。
      【解决方案3】:

      使用map[string]bool(以true 作为虚拟值)或map[string]struct{} 作为一个集合被认为是惯用的围棋。他们每个人都有自己的优点和缺点。

      假设:

      b := make(map[string]bool)
      s := make(map[string]struct{})
      
      1. 使用b 可以更轻松地检查集合是否包含元素:

        if b["x"] {
            // b has "x"
        }
        
        if _, ok := s["x"]; ok {
            // s has "x"
        }
        
      2. 除非您可以保证b 没有任何false 值,否则使用s 迭代元素会更容易:

        for e, v := range b {
            if v {
                // e is an element of b
            }
        }
        
        for e := range s {
            // e is an element of s
        }
        
      3. sb 更节省内存。

      作为替代方案,您可以使用开源库。例如:

      当然,目前不可能在 Go 中实现泛型集。但是随着 planned 在 Go 中添加泛型,它可以在更高版本(不早于 1.17)中实现。

      【讨论】:

        【解决方案4】:

        如果有人需要一组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

        【讨论】:

          猜你喜欢
          • 2017-02-24
          • 1970-01-01
          • 2010-10-28
          • 2011-12-29
          • 1970-01-01
          • 2011-04-28
          • 1970-01-01
          • 2011-01-19
          • 1970-01-01
          相关资源
          最近更新 更多