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

时间:2018-09-21 21:44:02

标签: go

我有以下多元数组:

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

我是否正确阅读此错误消息?

3 个答案:

答案 0 :(得分:3)

尽管此other answer提供了有关使用sort包的适当切片的指导,但我还是添加了此答案,以便对您发布的代码的其他一些问题提供更多说明。希望这有助于您理解Go语言。


切片简介

  

我理解排序函数需要没有已知大小的数组[sic]

就像其他人使用的said一样,这不是用Go语言描述此概念的术语。根据{{​​3}}的定义,所有Go数组的大小都是固定的。如您所知,数组的类型为[N]T,其中包含一些非负数N的元素,类型为T。这是在编译时固定的,在程序运行时不会更改。

“未知大小的数组”最紧密地映射到切片。切片是Go中不同的类型,可用于表示特定类型的数据序列,切片的长度由Go运行时动态管理。对于类型[]T的元素,它们的类型为T。特别是,它们的大小不是其类型定义的一部分,并且可以在运行时更改。对于某些切片变量x []T,该实现提供了:

  • 具有相似元素类型的内部支持数组,其中,该实现可管理内存分配以及随着切片长度的增加而扩展的数组
  • 其长度len(x) –表示切片当前包含的元素数量
  • 其容量cap(x) –切片的总长度加上辅助阵列的额外范围,由于切片操作限制了阵列上的视图,因此可能会超出该长度运行时分配一个更大的数组,以允许将更多项附加到切片。

有关更多详细信息,请参见language specTour of Go


解决代码问题

如上所述,切片是与数组不同的类型 ,因此对于某些[N]T和{ {1}}需要类型N的地方。

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

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

切片表达式以i的形式给出,其中[3]inta[low : high]是可选整数,它们提供支持数组或切片的索引,这些索引指定要在新切片中返回的范围。上面的语言规范链接提供了更多详细信息,我建议您阅读;足以说出某个数组或切片low的最简单切片表达式high是表示a[:]的语法糖,即将数组/切片转换为相同长度的切片。

使用此技巧,通过切片:a:从多维数组中获取类型为a[0:len(a)-1]的切片:

  • []int返回类型为x[i][:]的数组,像以前一样
  • 切片返回的数组将返回类型为x[i]的切片,该切片与[3]int兼容。

[]int不返回值,并且条带不可比

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

sort.Ints
  1. sort.Ints就地进行排序;它不会返回值,因此相等性测试毫无意义。
  2. t := sort.Ints(x[i]) == []int{1, 2, 3} 在无法比较的切片上运行。除非在sort.Intssort.Ints是特殊标识符A == B的情况下,否则无法调用AB是切片的Aslice expression中涵盖了这一点。 (此外:请阅读该页面,因为您会注意到数组 是可比较的。)

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

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

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

这可以通过遍历一个切片来验证,并且验证每个索引处的元素是否与另一个切片中的相同索引相对应。此示例代码提供了该示例(language spec):

nil

答案 1 :(得分: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
    }
}

答案 2 :(得分: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.