0

0

Go 中如何根据另一切片对切片进行排序(稳定映射排序)

心靈之曲

心靈之曲

发布时间:2026-01-05 13:12:08

|

409人浏览过

|

来源于php中文网

原创

Go 中如何根据另一切片对切片进行排序(稳定映射排序)

本文详解如何在 go 中实现「按参考切片值排序主切片」,即保持两切片索引映射关系的前提下,依据 `other_slice` 的升序排列重新组织 `main_slice` 元素,并指出常见错误(如遗漏 `other_slice` 的同步交换)及正确实现方式。

在 Go 中,若需根据一个“权重切片”(如 other_slice)对另一个“数据切片”(如 main_slice)进行排序,核心思路是:将两切片视为绑定的键值对,按 other_slice 的值升序重排索引,再据此重排 main_slice。这本质上是一种“索引协同排序”,要求 Swap 操作必须同时交换两个切片对应位置的元素;否则,Less 函数依赖的 other_slice[i] 和 other_slice[j] 关系会随 main_slice 乱序而失准,导致排序逻辑崩溃。

你提供的代码中,Swap 方法仅交换了 main_slice,却未同步更新 other_slice —— 这使得后续 Less 比较时读取的是错位后的 other_slice 值,排序依据失效。例如,初始时索引 2 对应 other_slice[2]==1(最小值),但第一次交换后该最小值可能被移走,而 Less 仍假设它仍在原位,最终结果自然不符合预期。

✅ 正确做法是:在 Swap 中严格同步交换两个切片。修正后的完整可运行代码如下:

AutoDraw
AutoDraw

AutoDraw是一个绘图工具,可以将草图转换成现成的模型图片

下载
package main

import (
    "fmt"
    "sort"
)

type TwoSlices struct {
    main_slice  []int
    other_slice []int
}

type SortByOther TwoSlices

func (sbo SortByOther) Len() int           { return len(sbo.main_slice) }
func (sbo SortByOther) Swap(i, j int)      {
    sbo.main_slice[i], sbo.main_slice[j] = sbo.main_slice[j], sbo.main_slice[i]
    sbo.other_slice[i], sbo.other_slice[j] = sbo.other_slice[j], sbo.other_slice[i] // ✅ 关键修复:同步交换
}
func (sbo SortByOther) Less(i, j int) bool { return sbo.other_slice[i] < sbo.other_slice[j] }

func main() {
    my_other_slice := []int{3, 5, 1, 2, 7}
    my_main_slice := []int{1, 2, 3, 4, 5} // 期望结果:{3,4,1,2,5}(因 other_slice 中 1,2,3,5,7 对应索引 2,3,0,1,4)

    my_two_slices := TwoSlices{
        main_slice:  my_main_slice,
        other_slice: my_other_slice,
    }

    fmt.Println("Not sorted:", my_two_slices.main_slice)
    sort.Sort(SortByOther(my_two_slices))
    fmt.Println("Sorted:    ", my_two_slices.main_slice)
    // 输出:Sorted:     [3 4 1 2 5]
}

? 注意事项与进阶建议

  • 不可变需求? 若原始 other_slice 需保持不变,应传入其副本(如 append([]int(nil), my_other_slice...)),避免副作用。
  • 稳定性保障:Go 的 sort.Sort 是不稳定的(相等元素相对顺序可能改变)。若需稳定排序(如 other_slice 存在重复值且需保持原索引顺序),可改用 sort.SliceStable 并基于索引切片排序:
    indices := make([]int, len(other_slice))
    for i := range indices { indices[i] = i }
    sort.SliceStable(indices, func(i, j int) bool {
        return other_slice[indices[i]] < other_slice[indices[j]]
    })
    // 再按 indices 重排 main_slice
  • 泛型优化(Go 1.18+):可封装为泛型函数,支持任意类型切片:
    func SortByReference[T any, K constraints.Ordered](main []T, ref []K) {
        if len(main) != len(ref) { panic("length mismatch") }
        sort.Slice(main, func(i, j int) bool { return ref[i] < ref[j] })
        // 注意:此方式不修改 ref,但需确保 ref 不被并发修改
    }

总结:协同排序的关键在于维护两切片的索引一致性,Swap 必须双切片同步操作。理解 sort.Interface 各方法的契约(尤其是 Swap 的语义)是避免此类逻辑错误的核心。

相关专题

更多
Sass和less的区别
Sass和less的区别

Sass和less的区别有语法差异、变量和混合器的定义方式、导入方式、运算符的支持、扩展性等。本专题为大家提供Sass和less相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.10.12

sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

381

2023.09.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

314

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

527

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

49

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

191

2025.08.29

go中interface用法
go中interface用法

本专题整合了go语言中int相关内容,阅读专题下面的文章了解更多详细内容。

76

2025.09.10

go语言 数组和切片
go语言 数组和切片

本专题整合了go语言数组和切片的区别与含义,阅读专题下面的文章了解更多详细内容。

45

2025.09.03

漫蛙2入口地址合集
漫蛙2入口地址合集

本专题整合了漫蛙2入口汇总,阅读专题下面的文章了解更多详细内容。

13

2026.01.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.4万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号