Go 1.21新增的 slices 包详解(三)

Go 1.21新增的 slices 包提供了很多和切片相关的函数,可以用于任何类型的切片。

slices.Max

定义如下:

复制代码
func Max[S ~[]E, E cmp.Ordered](x S) E

返回 x 中的最大值,如果 x 为空,则 panic。对于浮点数 E, 如果有元素为 NaN,结果就是 NaN。简单示例如下:

复制代码
package main

import (
	"fmt"
	"math"
	"slices"
)

func main() {
	numbers := []int{0, 10, -1, 8}
	fmt.Println(slices.Max(numbers)) // 10 

	numbers2 := []float64{0, 10, -1, 8, math.NaN()}
	fmt.Println(slices.Max(numbers2)) // NaN
}

slices.MaxFunc

定义如下:

复制代码
func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E

返回 x 中的最大值,使用 cmp 函数来比较元素,如果 x 为空,则 panic。如果根据 cmp 函数计算后有多个最大元素,返回第一个。简单示例如下:

复制代码
package main

import (
	"cmp"
	"fmt"
	"slices"
)

func main() {
	type Person struct {
		Name string
		Age  int
	}
	people := []Person{
		{"Gopher", 13},
		{"Alice", 55},
		{"Vera", 24},
		{"Bob", 55},
	}
	firstOldest := slices.MaxFunc(people, func(a, b Person) int {
		return cmp.Compare(a.Age, b.Age)
	})
	fmt.Println(firstOldest.Name) // Alice
}

slices.Min

定义如下:

复制代码
func Min[S ~[]E, E cmp.Ordered](x S) E

返回 x 中的最小值,如果 x 为空,则 panic。对于浮点数 E, 如果有元素为 NaN,结果就是 NaN。简单示例如下:

复制代码
package main

import (
	"fmt"
	"math"
	"slices"
)

func main() {
	numbers := []int{0, 10, -1, 8}
	fmt.Println(slices.Min(numbers)) // -1

	numbers2 := []float64{0, 10, -1, 8, math.NaN()}
	fmt.Println(slices.Min(numbers2)) // NaN
}

slices.MinFunc

定义如下:

复制代码
func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E

返回 x 中的最小值,使用 cmp 函数来比较元素,如果 x 为空,则 panic。如果根据 cmp 函数计算后有多个最小元素,返回第一个。简单示例如下:

复制代码
package main

import (
	"cmp"
	"fmt"
	"slices"
)

func main() {
	type Person struct {
		Name string
		Age  int
	}
	people := []Person{
		{"Gopher", 13},
		{"Alice", 55},
		{"Vera", 24},
		{"Bob", 55},
	}
	firstYoungest := slices.MinFunc(people, func(a, b Person) int {
		return cmp.Compare(a.Age, b.Age)
	})
	fmt.Println(firstYoungest.Name) // Gopher
}

slices.Replace

定义如下:

复制代码
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S

将元素 si:j 替换为给定的 v,并返回修改后的切片。如果 si:j 不是 s 的一部分,则 panic。简单示例如下:

复制代码
package main

import (
	"fmt"
	"slices"
)

func main() {
	names := []string{"Alice", "Bob", "Vera", "Zac"}
	names = slices.Replace(names, 1, 3, "Bill", "Billie", "Cat")
	fmt.Println(names) // [Alice Bill Billie Cat Zac]
}

slices.Reverse

定义如下:

复制代码
func Reverse[S ~[]E, E any](s S)

反转切片中的元素。简单示例如下:

复制代码
package main

import (
	"fmt"
	"slices"
)

func main() {
	names := []string{"alice", "Bob", "VERA"}
	slices.Reverse(names)
	fmt.Println(names) // [VERA Bob alice]
}

slices.Sort

定义如下:

复制代码
func Sort[S ~[]E, E cmp.Ordered](x S)

对有序类型的切片进行升序排序。对于浮点数类型,NaN 排在其它值之前。简单示例如下:

复制代码
package main

import (
	"fmt"
	"math"
	"slices"
)

func main() {
	s1 := []int8{0, 42, -10, 8}
	slices.Sort(s1) 
	fmt.Println(s1) // [-10 0 8 42]

	s2 := []float64{0, math.NaN(), -10, 8, math.NaN()}
	slices.Sort(s2)
	fmt.Println(s2) // [NaN NaN -10 0 8]
}

slices.SortFunc

定义如下:

复制代码
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int)

按照 cmp 函数确定的升序对切片 x 进行排序,这种排序不能保证稳定。Cmp (a, b) 函数应该在 a < b 时返回一个负数,在 a > b 时返回一个正数,在 a == b 时返回零。SortFunc 要求 cmp 函数是严格的弱排序类型。简单示例如下:

复制代码
package main

import (
	"cmp"
	"fmt"
	"slices"
	"strings"
)

func main() {
	names := []string{"Bob", "alice", "VERA"}
	slices.SortFunc(names, func(a, b string) int {
		return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
	})
	fmt.Println(names) // [alice Bob VERA]
}

slices.SortStableFunc

定义如下:

复制代码
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int)

对切片 x 进行排序,同时保持相等元素的原始顺序,使用 cmp 以与 SortFunc 相同的方式比较元素。简单示例如下:

复制代码
package main

import (
	"cmp"
	"fmt"
	"slices"
)

func main() {
	type Person struct {
		Name string
		Age  int
	}
	people := []Person{
		{"Gopher", 13},
		{"Alice", 20},
		{"Bob", 24},
		{"Alice", 55},
	}
	// Stable sort by name, keeping age ordering of Alices intact
	slices.SortStableFunc(people, func(a, b Person) int {
		return cmp.Compare(a.Name, b.Name)
	})
	fmt.Println(people) // [{Alice 20} {Alice 55} {Bob 24} {Gopher 13}]
}
相关推荐
ZWZhangYu41 分钟前
从 Dify 实践理解大模型上下文缓存
java·后端·spring
小熊恋旧44 分钟前
Python 面向对象编程:方法、属性、继承与多态详解
开发语言·python
云边云科技_云网融合1 小时前
面向汽车零部件制造业场景的解决方案 | 70 秒:一台车下线的时间里,藏着五张网
开发语言·汽车·php
Evand J1 小时前
【PMSM滤波例程2】PMSM未知负载转矩观测EKF。MATLAB例程(负载增广EKF与实际仿真结果)。附下载链接
开发语言·matlab·电机
will_net1 小时前
apollo 站点部署&C#接入
开发语言·c#·apollo
考虑考虑2 小时前
瀚高数据库
数据库·后端·postgresql
晗夜未央2 小时前
任务队列反复失败,先分清重试、阻塞和结果待核对
开发语言·javascript
熊猫钓鱼>_>2 小时前
四种书签,一条时间线:一个读书 App 的记忆颗粒与它的边界案例【鸿蒙心迹】
开发语言·华为·ai编程·harmonyos·鸿蒙·openharmony·鸿蒙pc
锋行天下2 小时前
DeepSeek写Langgraph就是个大傻逼,一本正经胡说八道
前端·人工智能·后端
努力努力再努力wz2 小时前
【Lua 入门系列】Lua 函数深入理解:函数对象、多返回值、可变参数、闭包、递归与尾调用优化
开发语言·lua