You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 07:10:09