【问题标题】:Is there a built in min function for a slice of int arguments or a variable number of int arguments in golang?golang 中是否有用于 int 参数切片或可变数量的 int 参数的内置 min 函数?
【发布时间】:2015-12-14 04:30:27
【问题描述】:

Precursor:我刚开始接触 golang。

这可能被证明是一个愚蠢的问题,因为执行这些计算很容易,但无论如何我都会问它,因为我在谷歌搜索时没有找到答案。

是否有一个内置函数可以返回 int 参数切片的最小值:

func MinIntSlice(v []int) (m int) {
    if len(v) > 0 {
        m = v[0]
    }
    for i := 1; i < len(v); i++ {
        if v[i] < m {
            m = v[i]
        }
    }
    return
}

或可变数量的 int 参数中的最小值:

func MinIntVarible(v1 int, vn ...int) (m int) {
    m = v1
    for i := 0; i < len(vn); i++ {
        if vn[i] < m {
            m = vn[i]
        }
    }
    return
}

如果不是,最好的“约定”是简单地创建一个包含这样的助手的包吗?

【问题讨论】:

    标签: go


    【解决方案1】:

    没有内置的。

    如果您只在一个包中需要此功能,您可以编写一个未导出的函数(例如minIntSlice)。

    如果您在多个包中需要此功能,您可以创建一个包并在其中放置类似的功能。你应该考虑把这个包放在内部 (https://golang.org/s/go14internal)。

    关于如何改进代码的一些建议:

    1. MinIntSlice 将为空切片返回 0。然而 0 也是一个有效的最小元素。我认为在空切片上调用 panic 是一个更好的选择。

    2. 使用范围循环:

      for i, e := range v {
          if i==0 || e < m {
              m = e
          }
      }
      

    如果不给出值的索引,它会给你最小值 0,它可能不存在于给定的值中,所以你还必须对索引应用条件。

    【讨论】:

    • 这是一个有用的反馈。我还没有接触过“范围”。
    • 感谢您提供指向“内部”包的指针。我确实复制了这样的未导出函数,内部看起来是更好地维护这些函数的方法。
    【解决方案2】:

    正如@kostya 正确指出的那样,Golang 中没有内置的 min 或 max 函数。

    但是,我会建议一个稍微不同的解决方案:

    func MinMax(array []int) (int, int) {
        var max int = array[0]
        var min int = array[0]
        for _, value := range array {
            if max < value {
                max = value
            }
            if min > value {
                min = value
            }
        }
        return min, max
    }
    

    这样就解决了空切片的问题:出现运行时错误(index out of range)并且最大值是免费的。 :-)

    【讨论】:

      【解决方案3】:
          min := s[0]
          for i :=1; i < len(s); i++ {
              if min > s[i] {
                  min = s[i]
              }
          }
      

      min &gt; s[i]? min = s[i] : min

      【讨论】:

      • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。
      【解决方案4】:

      This package 包含 MinMax 函数的一些实现,用于单独的值或切片。在go get 之后可以这样使用:

      import (
          "fmt"
          "<Full URL>/go-imath/ix" // Functions for int type
      )
      ...
      fmt.Println(ix.Min(100, 152)) // Output: 100
      fmt.Println(ix.Mins(234, 55, 180)) // Output: 55
      fmt.Println(ix.MinSlice([]int{2, 29, 8, -1})) // Output: -1
      

      【讨论】:

        【解决方案5】:

        如果你不关心输入数组

        import . "sort"
        func MinIntSlice(v []int){
            Ints(v)
            return z[0]
        }
        
        func MaxIntSlice(v []int){
            Ints(v)
            return z[len(v)-1]
        }
        // and MinMax version
        func MinMax(v []int)(int,int){
            Ints(v)
            return z[0],z[len(v)-1]
        }
        

        【讨论】:

          【解决方案6】:

          排序可以更短:

          func MinIntSlice(v []int) int {
            sort.Ints(v)
            return v[0]
          }
          
          func MaxIntSlice(v []int) int {
            sort.Ints(v)
            return v[len(v)-1]
          }
          

          但不要忘记根据您的喜好将其修改为零长度切片。

          【讨论】:

          • 改变底层切片只是为了挑选一些东西是一个糟糕的主意。这可能会改变关于其他地方隐式排序的断言
          • 排序是 o(n log n) 但最大值是线性时间 o(n) 算法,这个“代码更短”但算法更差。
          • 是的,它远非最佳。但是,当您在算法中间某处需要小切片的最小值/最大值时,可以对其进行排序并取第一个/最后一个,而不是制作您永远不会再使用的单独函数。
          • @fullpipe 切片按值传递。不是基础数据。它将被修改。
          【解决方案7】:

          使用@kostya 的answer

          1. 使用范围循环:

            for i, e := range v {
                if i==0 || e < m {
                    m = e
                }
            }
            

          如果不给出值的索引,它会给你最小值 0,它可能不存在于给定的值中

          【讨论】:

            猜你喜欢
            • 2015-03-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-25
            • 1970-01-01
            • 1970-01-01
            • 2020-05-25
            • 2013-01-11
            相关资源
            最近更新 更多