Go语言sort.Slice()排序结果不符预期,是否为sort包Bug?
这不是Go sort包的Bug,是排序逻辑的问题
先明确核心问题:你想基于m的降序对rank排序,但当前写法没处理m元素相等时的顺序规则,再加上sort.Slice用的是不稳定排序,才导致结果不符合预期。
你的比较函数func(i, j int) bool { return m[i] > m[j] }存在逻辑缺口:当m[i] == m[j]时,函数返回false,这时候sort.Slice的不稳定排序算法会随意调整这两个元素的位置,无法保证它们在rank中的原始顺序。比如你例子里m[0]和m[3]都是1,对应的rank值0和3,排序时它们的位置可能被调换,就出现了和预期不符的结果。
两种正确实现方式
方式一:用索引切片间接排序
这种方式逻辑清晰,先对索引按m的值排序,再根据排序后的索引重新生成rank:
func main() { m := []int{1, 3, 2, 1, 0, 0} rank := []int{0, 1, 2, 3, 4, 5} // 生成索引切片 indices := make([]int, len(m)) for i := range indices { indices[i] = i } // 按m降序排序索引,相等时保留原始顺序 sort.SliceStable(indices, func(i, j int) bool { return m[indices[i]] > m[indices[j]] }) // 根据排序后的索引构建结果 sortedRank := make([]int, len(rank)) for i, idx := range indices { sortedRank[i] = rank[idx] } fmt.Println(sortedRank) // 输出 [1 2 0 3 4 5] }
方式二:用稳定排序+补充相等元素规则
直接用sort.SliceStable替代sort.Slice,并在m元素相等时,通过原始索引的大小来保证顺序:
func main() { m := []int{1, 3, 2, 1, 0, 0} rank := []int{0, 1, 2, 3, 4, 5} sort.SliceStable(rank, func(i, j int) bool { if m[i] != m[j] { return m[i] > m[j] } // m值相等时,按原始索引升序排列,保留rank的原始顺序 return i < j }) fmt.Println(rank) // 输出 [1 2 0 3 4 5] }
关键知识点
sort.Slice采用不稳定排序算法,相等元素的顺序不做保证,这是设计特性而非Bug- 若需要保留相等元素的原始顺序,必须使用
sort.SliceStable,或者通过索引切片间接控制排序逻辑
内容的提问来源于stack exchange,提问作者Fizz
相关产品推荐
相关产品推荐

