Golang1.21-slices package
目录
Go1.21新增了slices包,该包提供了slice相关的工具函数。
相关issue: https://github.com/golang/go/issues/57433
slices pkg中提供了部分相关的example。
二分查找⌗
可参考
压缩⌗
可参考
需要注意的是,这里的压缩是针对相邻的元素,如果相等的元素间隔排列,则不会被压缩。
fmt.Println("slices.Compact")
seq := []int{0, 1, 1, 2, 1, 3, 5, 8}
fmt.Printf("%v len(seq)=%d\n", seq, len(seq))
seq = slices.Compact(seq)
fmt.Printf("%v len(seq)=%d\n", seq, len(seq))
// output
// [0 1 1 2 1 3 5 8] len(seq)=8
// [0 1 2 1 3 5 8] len(seq)=7
比较⌗
可参考
删除⌗
可参考
查找位置⌗
可参考
是否已经排序⌗
可参考
需要注意的是,这里都只是检查是否按照升序进行排序。如果是降序或者无序,则返回false。
fmt.Println(slices.IsSorted([]int{0, 1, 2})) // true
fmt.Println(slices.IsSorted([]int{0, 2, 1})) // false
fmt.Println(slices.IsSorted([]int{2, 1, 0})) // false
最大值,最小值⌗
可参考
需要注意的是,如果slice为空,则会panic。
numbers := []int{}
slices.Max(numbers) // panic: slices.Max: empty list
是否包含⌗
Contains函数可以用来判断slice中是否包含某个元素,内部实现用了Index
函数。
s := []string{"Apple", "Banana", "Orange"}
fmt.Println("Have Apple?", slices.Contains(s, "Apple"))
替换⌗
可参考
originalNames := []string{"Alice", "Bob", "Vera", "Zac"}
fmt.Printf("%v\n", originalNames)
// 替换[1, 3) 之间的元素,替换的元素个数没必要和被替换的元素个数相同
names := slices.Replace(originalNames, 1, 3, "Bill", "Billie", "Cat")
fmt.Printf("%v\n", names)
names = slices.Replace(originalNames, 0, 0, "Bill", "Billie", "Cat")
fmt.Printf("%v\n", names)
逆序⌗
可参考
排序⌗
可参考
SortStableFunc
内部使用了插入排序,而SortFunc
内部使用了快速排序(其实是Pattern-defeating quicksort)。
缩容⌗
Clip函数可以从slice中移除不必要的容量。这可以在运行时在slices占用过多内存的时候,释放内存。
s := make([]int, 0, 10)
s = append(s, 1, 2, 3)
fmt.Printf("%v len=%d cap=%d %p\n", s, len(s), cap(s), s)
// output
// [1 2 3] len=3 cap=10 0xc0000b4050
afterClip := slices.Clip(s)
fmt.Printf("%v len=%d cap=%d %p\n", afterClip, len(afterClip), cap(afterClip), afterClip)
// output
// [1 2 3] len=3 cap=3 0xc0000b4050
本质上该函数的工作就是s[:len(s):len(s)]
。
扩容⌗
Grow函数可以扩容slice的容量,如果slice的容量不够,那么就会扩容。
s := make([]int, 0, 10)
s = append(s, 1, 2, 3)
fmt.Printf("%v len=%d cap=%d %p\n", s, len(s), cap(s), s)
// output
// [1 2 3] len=3 cap=10 0xc000120050
afterGrow := slices.Grow(s, 20)
fmt.Printf("%v len=%d cap=%d %p\n", afterGrow, len(afterGrow), cap(afterGrow), afterGrow)
// output
// [1 2 3] len=3 cap=24 0xc00012a000
需要注意的是,如果Grow的第二个参数为负数或过大无法分配内存的时候,就会panic。
克隆⌗
Clone函数可以克隆一个slice,需要注意的是它是浅拷贝。
type Person struct {
Name string
}
people := []Person{
{Name: "bob"},
{Name: "alice"},
}
clonePeople := slices.Clone(people)
fmt.Printf("clonePeople %v %p\n", clonePeople, clonePeople)
// output
// [{bob} {alice}] 0xc0000b40e0
clonePeople[0].Name = "Bob"
fmt.Printf("clonePeople %v %p\n", clonePeople, clonePeople)
// output
// [{Bob} {alice}] 0xc0000b40e0
fmt.Printf("people %v %p\n", people, people)
// output
// [{Bob} {alice}] 0xc0000b40e0
Read other posts