golang切片通用操作函数库slices的使用
Golang切片通用操作函数库slices的使用
slices是一个提供纯函数式切片操作的Go语言库,所有操作都不会修改原切片,而是返回新的切片。
安装
go get github.com/twharmon/slices
使用示例
下面是一个完整的使用示例,展示了slices库的主要功能:
package main
import (
"fmt"
"github.com/twharmon/slices"
)
func main() {
// 使用普通的Go切片
s := []string{"foo", "ba"}
// 在切片末尾追加新元素
s = slices.Append(s, "b")
fmt.Println(s) // [foo ba b]
// 按字符串长度升序排序
sorted := slices.SortFunc(s, func(a, b string) bool {
return len(a) < len(b)
})
// 原切片不会被修改
fmt.Println(s, sorted) // [foo ba b] [b ba foo]
// 计算所有字符串长度的总和
totalLen := slices.Reduce(s, func(cnt int, i string) int {
return cnt + len(i)
})
fmt.Println(totalLen) // 6
// 查找第一个长度为2的字符串
str := slices.Find(s, func(item string) bool { return len(item) == 2 })
fmt.Println(str) // ba
// 将字符串切片映射为整数切片
ints := slices.Map(s, func(item string) int { return len(item) })
fmt.Println(ints) // [3 2 1]
}
主要功能
- Append: 在切片末尾追加元素
- SortFunc: 使用自定义比较函数排序切片
- Reduce: 将切片缩减为单个值
- Find: 查找满足条件的第一个元素
- Map: 将切片映射为另一种类型的切片
性能基准测试
goos: darwin
goarch: arm64
pkg: github.com/twharmon/slices
BenchmarkSortFunc/std_lib-10 116497 9424 ns/op 4152 B/op 3 allocs/op
BenchmarkSortFunc/slices-10 101791 11479 ns/op 4096 B/op 1 allocs/op
BenchmarkSort/std_lib-10 125790 9441 ns/op 4120 B/op 2 allocs/op
BenchmarkSort/slices-10 113931 10162 ns/op 4096 B/op 1 allocs/op
BenchmarkReverse-10 1631348 749.4 ns/op 4096 B/op 1 allocs/op
BenchmarkConcat-10 275463 4259 ns/op 40960 B/op 1 allocs/op
BenchmarkFilter-10 1000000 1018 ns/op 4096 B/op 1 allocs/op
贡献
欢迎通过提交Pull Request来贡献代码。
更多关于golang切片通用操作函数库slices的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang切片通用操作函数库slices的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
Golang切片通用操作函数库slices使用指南
Go 1.21标准库中引入了新的slices
包,提供了一系列用于切片操作的通用函数。下面我将详细介绍这个库的主要功能和使用方法。
基本介绍
slices
包提供了对任意元素类型的切片进行操作的功能,类似于其他语言中的泛型集合操作。要使用它,需要导入:
import "slices"
主要功能及示例
1. 比较操作
func Equal[S ~[]E, E comparable](s1, s2 S) bool
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool
示例:
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 3}
s3 := []int{1, 2, 4}
fmt.Println(slices.Equal(s1, s2)) // true
fmt.Println(slices.Equal(s1, s3)) // false
// 自定义比较函数
names := []string{"Alice", "Bob"}
names2 := []string{"ALICE", "BOB"}
equal := slices.EqualFunc(names, names2, func(a, b string) bool {
return strings.EqualFold(a, b)
})
fmt.Println(equal) // true
2. 排序和搜索
func Sort[S ~[]E, E cmp.Ordered](x S)
func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int)
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int)
func IsSorted[S ~[]E, E cmp.Ordered](x S) bool
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool
func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)
func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool)
示例:
nums := []int{3, 1, 4, 1, 5, 9}
slices.Sort(nums)
fmt.Println(nums) // [1 1 3 4 5 9]
// 自定义排序
people := []struct {
Name string
Age int
}{
{"Alice", 25},
{"Bob", 30},
{"Charlie", 20},
}
slices.SortFunc(people, func(a, b struct {
Name string
Age int
}) int {
return cmp.Compare(a.Age, b.Age)
})
fmt.Println(people) // [{Charlie 20} {Alice 25} {Bob 30}]
// 二分查找
idx, found := slices.BinarySearch(nums, 4)
fmt.Println(idx, found) // 3 true
3. 切片操作
func Clone[S ~[]E, E any](s S) S
func Compact[S ~[]E, E comparable](s S) S
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S
func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int
func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int
func Contains[S ~[]E, E comparable](s S, v E) bool
func Delete[S ~[]E, E any](s S, i, j int) S
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S
func Grow[S ~[]E, E any](s S, n int) S
func Index[S ~[]E, E comparable](s S, v E) int
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int
func Insert[S ~[]E, E any](s S, i int, v ...E) S
func Replace[S ~[]E, E any](s S, i, j int, v ...E) S
func Reverse[S ~[]E, E any](s S)
示例:
// 克隆切片
original := []int{1, 2, 3}
clone := slices.Clone(original)
fmt.Println(clone) // [1 2 3]
// 去重
nums := []int{1, 1, 2, 3, 3, 3}
unique := slices.Compact(nums)
fmt.Println(unique) // [1 2 3]
// 包含检查
fmt.Println(slices.Contains(nums, 2)) // true
// 删除元素
s := []int{1, 2, 3, 4, 5}
s = slices.Delete(s, 1, 3) // 删除索引1到3(不包括3)的元素
fmt.Println(s) // [1 4 5]
// 插入元素
s = slices.Insert(s, 1, 2, 3)
fmt.Println(s) // [1 2 3 4 5]
// 反转切片
slices.Reverse(s)
fmt.Println(s) // [5 4 3 2 1]
4. 转换和过滤
func Concat[S ~[]E, E any](slices ...S) S
func Filter[S ~[]E, E any](s S, f func(E) bool) S
示例:
// 连接多个切片
s1 := []int{1, 2}
s2 := []int{3, 4}
combined := slices.Concat(s1, s2)
fmt.Println(combined) // [1 2 3 4]
// 过滤
numbers := []int{1, 2, 3, 4, 5, 6}
evens := slices.Filter(numbers, func(n int) bool {
return n%2 == 0
})
fmt.Println(evens) // [2 4 6]
注意事项
- 大多数函数返回新切片而不是修改原切片,但有些函数如
Sort
会直接修改原切片 - 使用泛型函数时,类型必须满足相应的约束条件
- 对于大型切片,某些操作可能会有性能考虑
slices
包极大地简化了Go中对切片的常见操作,减少了样板代码的编写,是Go 1.21中非常实用的新增功能。