如何在golang中对固定长度的数组进行排序?

问题描述 投票:0回答:3

我有以下多变量数组:

x := [2][3]int{
    {3, 2, 1},
    {3, 2, 1},
}

行和列都是固定大小的。

我正在尝试检查行是否已排序,并且我认为sort函数需要没有已知大小的数组。我怎么能要求用固定的,已知的尺寸处理该物品,就好像它的尺寸未知一样?

var allTrue bool = true
for i := range x {
  t := sort.Ints(x[i]) == []int{1, 2, 3}
  allTrue = allTrue && t
}

我明白了:

./main.go:xx:yy: sort.Ints(x[i]) used as value
./main.go:xx:yy: cannot use x[i] (type [3]int) as type []int in argument to sort.Ints

我正确阅读此错误消息吗?

go
3个回答
3
投票

尽管有这个other answer,它提供了关于使用sort包的适当切片的指导,但我添加了这个答案,以提供有关您发布的代码的一些进一步问题的更多描述。我希望这有助于您理解Go语言。


切片介绍

我理解sort函数需要没有已知大小的数组[原文如此]

由于其他人有said,这不是在Go中描述这个概念的术语。所有Go数组都是固定大小的,由language spec定义。如您所知,数组的类型为[N]T,其中包含一些N类型的非负数T。这是在编译时修复的,在程序运行期间永远不会更改。

“没有已知大小的数组”最接近切片。切片是Go中的不同类型,允许表示特定类型的数据序列,其长度由Go运行时动态管理。对于[]T类型的元素,它们是T类型。特别是,它们的大小不是其类型定义的一部分,可以在运行时更改。对于一些切片变量x []T,实现提供:

  • 类似元素类型的内部后备数组,其中实现在切片长度增加时管理内存的分配和数组的扩展
  • 其长度len(x) - 表示切片当前包含的元素数
  • 它的容量cap(x) - 切片的总长度加上后备数组的附加范围,由于限制数组视图的切片操作或运行时分配的更大数组允许追加更多项目,因此可能会超出长度切片。

有关详细信息,请参阅Tour of Golanguage spec on slices


用代码解决问题

如上所述,切片与数组的类型不同,所以你不能使用[N]T类型的东西用于某些需要N类型的T[]T

sort.Ints在原地对一片整数进行排序 - 它有类型签名func Ints(a []int)。你的调用sort.Ints(x[i])将索引x的数组i编入索引,这将返回[3]int类型的数组。这与sort函数不兼容,并导致您观察到的编译时错误。

要从数组中获取切片,请使用slice expression。这样的表达式允许使用数组,切片和一些其他类型来构造新切片。

切片表达式以a[low : high]的形式给出,其中lowhigh是可选整数,为后备数组或切片提供索引,指定要在新切片中返回的范围。上面的语言规范链接有更多细节,我建议你阅读;可以说,对于某些阵列或切片a[:],最简单的切片表达式a是语法糖,意思是a[0:len(a)-1],即将阵列/切片转换成相同长度的切片。

使用此技巧,通过切片从多维数组中获取切片[]intx[i][:]

  • x[i]像以前一样返回[3]int类型的数组
  • 切片返回的数组返回一个[]int类型的切片,它与sort.Ints兼容。

sort.Ints没有返回值,并且切片不具有可比性

即使您使用代码解决了这些问题,以下行仍然存在两个问题:

t := sort.Ints(x[i]) == []int{1, 2, 3}
  1. sort.Ints就地排序;它没有返回值,所以相等测试毫无意义。
  2. sort.Ints采用切片进行操作,无法比较。除非A == BA是特殊标识符B,否则无法调用A,其中Bnil是切片。这是language spec所涵盖的一个微妙点。 (旁白:阅读该页面,因为您会注意到阵列具有可比性。)

由于无法直接使用==相等运算符比较切片,因此验证切片的元素相等性需要:

  • 切片长度相同(不同长度意味着一个切片比另一个切片具有更多元素)
  • 一个切片的每个索引处的元素与其他切片相同。

(我忽略了一个切片可能与另一个切片具有不同容量的事实,因为我们只关心元素明确的等式。)

这可以通过循环其中一个切片来验证,并且验证每个索引处的元素对应于另一个切片中的相同索引。此示例代码提供了一个示例(playground link):

package main

import (
    "fmt"
)

func CheckEquality(a, b []int) bool {
    // Slices of dissimilar length are not equal
    if len(a) != len(b) {
        return false
    }

    for i, el := range a {
        if b[i] != el {
            return false
        }
    }

    return true
}

func main() {
    var mySlice = []int{1, 2, 3, 4, 5}
    var mySlice2 = []int{1, 2, 3, 4, 5}   // same as mySlice
    var otherSlice = []int{5, 6, 7, 8, 9} // dissimilar slice
    var longSlice = []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

    fmt.Println(CheckEquality(mySlice, mySlice2))   // Expect true
    fmt.Println(CheckEquality(mySlice, otherSlice)) // Expect false
    fmt.Println(CheckEquality(mySlice, longSlice))  // Expect false
}

2
投票

您必须先使用[:]运算符对数组进行切片,然后才能将其与sort包一起使用。见:A Tour of Go: Slices"sort" package godoc

此外,您可以使用sort.IntsAreSorted([]int)检查切片是否比排序切片更有效。

var allTrue bool = true
for i := range x {
    if !sort.IntsAreSorted(x[i][:]) {
        allTrue = false
        break
    }
}

1
投票

您可以使用[:]运算符从数组中获取切片,例如:

arr := [3]int{1, 2, 3}
slc := arr[:] // []int{1, 2, 3}, backed by arr

因此,您可以使用sort.Ints(...)函数:

sort.Ints(x[0][:])
sort.Ints(x[1][:])
// Now both elements of "x" are sorted.
© www.soinside.com 2019 - 2024. All rights reserved.