slices in Go 1.21
Go 1.21中新增的 slices
包中提供了很多与切片相关的函数,适用于任意类型的切片。
本文内容来自官方文档
BinarySearch
函数签名如下:
func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool)
BinarySearch
在已排序的切片中搜索 target
并返回找到 target
的位置,或者 target
在排序顺序中出现的位置;它还返回一个布尔值,表示是否确实在切片中找到了目标。切片必须按升序排序。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
names := []string{"Alice", "Bob", "Vera"}
n, found := slices.BinarySearch(names, "Vera")
fmt.Println("Vera:", n, found) // Vera: 2 true
n, found = slices.BinarySearch(names, "Bill")
fmt.Println("Bill:", n, found) // Bill: 1 false
}
BinarySearchFunc
函数签名如下:
func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool)
BinarySearchFunc
的工作方式类似于BinarySearch
,但使用自定义比较函数。切片必须按递增顺序排序,其中“递增”由cmp
定义。如果切片元素与目标匹配,则cmp
应返回0
;如果切片元素在目标之前,则返回负数;如果切片元素在目标之后,则返回正数。cmp
必须实现与切片相同的排序,这样如果cmp(a, t) < 0
且cmp(b, t) >= 0
,则切片中a
必须位于b
之前。
示例:
package main
import (
"cmp"
"fmt"
"slices"
)
func main() {
type Person struct {
Name string
Age int
}
people := []Person{
{"Alice", 55},
{"Bob", 24},
{"Gopher", 13},
}
n, found := slices.BinarySearchFunc(people, Person{"Bob", 0}, func(a, b Person) int {
return cmp.Compare(a.Name, b.Name)
})
fmt.Println("Bob:", n, found) // Bob: 1 true
}
Clip
函数签名如下:
func Clip[S ~[]E, E any](s S) S
Clip
从切片中删除未使用的容量,返回s[:len(s):len(s)]
。
Clone
函数签名如下:
func Clone[S ~[]E, E any](s S) S
Clone
返回切片的副本。使用赋值来复制元素,因此这是浅拷贝。
Compact
函数签名如下:
func Compact[S ~[]E, E comparable](s S) S
Compact
用单个副本替换连续运行的相同元素。这类似于Unix
上的uniq
命令。Compact
修改切片s
的内容并返回修改后的切片,该切片的长度可能更小。当Compact
总共丢弃m
个元素时,它可能不会修改元素s[len(s)-m:len(s)]
。如果这些元素包含指针,可能要考虑将这些元素清零,以便它们引用的对象可以被回收。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
seq := []int{0, 1, 1, 2, 3, 5, 8}
seq = slices.Compact(seq)
fmt.Println(seq) // [0 1 2 3 5 8]
}
CompactFunc
函数签名如下:
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S
CompactFunc
类似于Compact
,但使用相等函数来比较元素。对于比较相等的元素运行,CompactFunc
保留第一个。
示例:
package main
import (
"fmt"
"slices"
"strings"
)
func main() {
names := []string{"bob", "Bob", "alice", "Vera", "VERA"}
names = slices.CompactFunc(names, func(a, b string) bool {
return strings.ToLower(a) == strings.ToLower(b)
})
fmt.Println(names) // [bob alice Vera]
}
Compare
函数签名如下:
func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int
Compare
对每对元素使用cmp.Compare
来比较s1
和s2
的元素。从索引0
开始按顺序比较元素,直到一个元素不等于另一个元素。返回第一个不匹配元素的比较结果。如果两个切片在其中一个结束之前都相等,则认为较短的切片小于较长的切片。如果s1 == s2
,结果为0
;如果s1 < s2
,结果为-1
;如果s1 > s2
,结果为+1
。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
names := []string{"Alice", "Bob", "Vera"}
fmt.Println("Equal:", slices.Compare(names, []string{"Alice", "Bob", "Vera"})) // Equal: 0
fmt.Println("V < X:", slices.Compare(names, []string{"Alice", "Bob", "Xena"})) // V < X: -1
fmt.Println("V > C:", slices.Compare(names, []string{"Alice", "Bob", "Cat"})) // V > C: 1
fmt.Println("3 > 2:", slices.Compare(names, []string{"Alice", "Bob"})) // 3 > 2: 1
}
CompareFunc
函数签名如下:
func CompareFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, cmp func(E1, E2) int) int
CompareFunc
类似于Compare
,但对每对元素使用自定义比较函数。结果是cmp
的第一个非零结果;如果cmp
始终返回0
:
- 如果
len(s1) == len(s2)
,则结果为0
; - 如果
len(s1) < len(s2)
,则结果为-1
; - 如果
len(s1) > len(s2)
,则结果为+1
。
示例:
import (
"cmp"
"fmt"
"slices"
"strconv"
)
func main() {
numbers := []int{0, 43, 8}
strings := []string{"0", "0", "8"}
result := slices.CompareFunc(numbers, strings, func(n int, s string) int {
sn, err := strconv.Atoi(s)
if err != nil {
return 1
}
return cmp.Compare(n, sn)
})
fmt.Println(result) // 1
}
Contains
函数签名如下:
func Contains[S ~[]E, E comparable](s S, v E) bool
Contains
返回v
是否存在于s
中。
ContainsFunc
函数签名如下:
func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool
ContainsFunc
返回s
中是否至少有一个元素e
满足f(e)
。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{0, 42, -10, 8}
hasNegative := slices.ContainsFunc(numbers, func(n int) bool {
return n < 0
})
fmt.Println("Has a negative:", hasNegative) // Has a negative: true
hasOdd := slices.ContainsFunc(numbers, func(n int) bool {
return n%2 != 0
})
fmt.Println("Has an odd number:", hasOdd) // Has an odd number: false
}
Delete
函数签名如下:
func Delete[S ~[]E, E any](s S, i, j int) S
Delete
从s
中删除元素s[i:j]
,返回修改后的切片。如果s[i:j]
不是s
的有效切片,则产生panic
。删除的时间复杂度为O(len(s)-j)
,因此如果必须删除许多项,最好通过一次调用将它们全部删除,而不是一次删除一项。删除可能不会修改元素s[len(s)-(j-i):len(s)]
。如果这些元素包含指针,还需要考虑将这些元素归零,以便它们引用的对象可以被回收。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
letters := []string{"a", "b", "c", "d", "e"}
letters = slices.Delete(letters, 1, 4)
fmt.Println(letters) // [a e]
}
DeleteFunc
函数签名如下:
func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S
DeleteFunc
从s
中删除函数del(e)
返回true
的所有元素,并返回修改后的切片。当DeleteFunc
删除m
个元素时,它可能不会修改元素s[len(s)-m:len(s)]
。如果这些元素包含指针,还需要考虑将这些元素归零,以便它们引用的对象可以被回收。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
seq := []int{0, 1, 1, 2, 3, 5, 8}
seq = slices.DeleteFunc(seq, func(n int) bool {
return n%2 != 0 // delete the odd numbers
})
fmt.Println(seq) // [0 2 8]
}
Equal
函数签名如下:
func Equal[S ~[]E, E comparable](s1, s2 S) bool
Equal
报告两个切片是否相等:长度相同且所有元素相等,返回true
。如果长度不同,返回false
。否则,按递增的索引顺序比较元素,并且比较在第一个不相等的对处停止。浮点NaN
不被视为相等。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{0, 42, 8}
fmt.Println(slices.Equal(numbers, []int{0, 42, 8})) // true
fmt.Println(slices.Equal(numbers, []int{10})) // false
}
EqualFunc
func EqualFunc[S1 ~[]E1, S2 ~[]E2, E1, E2 any](s1 S1, s2 S2, eq func(E1, E2) bool) bool
EqualFunc
在每对元素上使用相等函数来报告两个切片是否相等。如果长度不同,EqualFunc
返回false
。否则,按递增索引顺序比较元素,并且比较在eq
返回false
的第一个索引处停止。
示例:
package main
import (
"fmt"
"slices"
"strconv"
)
func main() {
numbers := []int{0, 42, 8}
strings := []string{"000", "42", "0o10"}
equal := slices.EqualFunc(numbers, strings, func(n int, s string) bool {
sn, err := strconv.ParseInt(s, 0, 64)
if err != nil {
return false
}
return n == int(sn)
})
fmt.Println(equal) // true
}
Grow
函数签名如下:
func Grow[S ~[]E, E any](s S, n int) S
必要时,Grow
会增加切片的容量,以保证另外n
个元素的空间。在Grow(n)
之后,至少可以将n
个元素附加到切片,而无需再次分配。如果n
为负数或太大而无法分配内存,Grow 会出现panic
。
Index
函数签名如下:
func Index[S ~[]E, E comparable](s S, v E) int
Index
返回v
在s
中第一次出现的索引,如果不存在则返回-1
。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{0, 42, 8}
fmt.Println(slices.Index(numbers, 8)) // 2
fmt.Println(slices.Index(numbers, 7)) // -1
}
IndexFunc
函数签名如下:
func IndexFunc[S ~[]E, E any](s S, f func(E) bool) int
Index
返回s
中第一次符合f(e)
的元素的索引,如果不存在则返回-1
。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
numbers := []int{0, 42, -10, 8}
i := slices.IndexFunc(numbers, func(n int) bool {
return n < 0
})
fmt.Println("First negative at index", i) // First negative at index 2
}
Insert
函数签名如下:
func Insert[S ~[]E, E any](s S, i int, v ...E) S
Insert
将值v...
插入到索引i
处的s
中,返回修改后的切片。s[i:]
处的元素向上移动以腾出空间。在返回的切片r
中,r[i] == v[0]
,并且r[i+len(v)] ==
最初位于r[i]
的值。如果i
超出范围,则panic
。该函数的复杂度为O(len(s) + len(v))
。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
names := []string{"Alice", "Bob", "Vera"}
names = slices.Insert(names, 1, "Bill", "Billie")
names = slices.Insert(names, len(names), "Zac")
fmt.Println(names) // [Alice Bill Billie Bob Vera Zac]
}
IsSorted
函数签名如下:
func IsSorted[S ~[]E, E cmp.Ordered](x S) bool
IsSorted
返回x
是否按升序排序。
示例:
package main
import (
"fmt"
"slices"
)
func main() {
fmt.Println(slices.IsSorted([]string{"Alice", "Bob", "Vera"})) // true
fmt.Println(slices.IsSorted([]int{0, 2, 1})) // false
}
IsSortedFunc
函数签名如下:
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool
IsSortedFunc
返回x
是否按升序排序,使用cmp
作为比较函数。
示例:
package main
import (
"cmp"
"fmt"
"slices"
"strings"
)
func main() {
names := []string{"alice", "Bob", "VERA"}
isSortedInsensitive := slices.IsSortedFunc(names, func(a, b string) int {
return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
})
fmt.Println(isSortedInsensitive) // true
fmt.Println(slices.IsSorted(names)) // false
}

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
slices in Go 1.21的更多相关文章
- [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列
A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...
- 【夯实Mysql基础】MySQL性能优化的21个最佳实践 和 mysql使用索引
本文地址 分享提纲: 1.为查询缓存优化你的查询 2. EXPLAIN 你的 SELECT 查询 3. 当只要一行数据时使用 LIMIT 1 4. 为搜索字段建索引 5. 在Join表的时候使用相当类 ...
- 2-1 Linux 操作系统及常用命令
根据马哥linux初级视频 2-1.2-2来编辑 1. GUI与CLI GUI: Graphic User Interface CLI: Command Line Interface 注:在Windo ...
- Fedora 21 安装 Nvidia 驱动以及失败后的补救方法
在 Linux 桌面系统下玩了这么久,大部分时间都是使用 Ubuntu,偶尔使用一下 Fedora.我的电脑中安装有多个 Linux 发行版,见这里<在同一个硬盘上安装多个Linux发行版及Fe ...
- 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验
在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...
- CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身
CSharpGL(21)用鼠标拾取.拖拽VBO图元内的点.线或本身 效果图 以最常见的三角形网格(用GL_TRIANGLES方式进行渲染)为例. 在拾取模式为GeometryType.Point时,你 ...
- ABP(现代ASP.NET样板开发框架)系列之21、ABP展现层——Javascript函数库
点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之21.ABP展现层——Javascript函数库 ABP是“ASP.NET Boilerplate Project ...
- C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密
在上篇随笔<C#开发微信门户及应用(19)-微信企业号的消息发送(文本.图片.文件.语音.视频.图文消息等)>介绍了有关企业号的消息发送,官方特别声明消息是不用加密发送的.但是在回调的服务 ...
- [LeetCode] Arithmetic Slices 算数切片
A sequence of number is called arithmetic if it consists of at least three elements and if the diffe ...
- 【转】MySQL性能优化的最佳21条经验
文章转自: http://blog.csdn.net/waferleo/article/details/7179009 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...
随机推荐
- PMP 如何获取 PDU PMP 证书续证
PMP 如何获取 PDU. PMP 证书续证 需要准备一张带支付美元的信用卡 打开官网,登录: https://ccrs.pmi.org/ 内容随便填 ,可以到 https://pmichina ...
- Netty 框架学习 —— 初识 Netty
Netty 是一款异步的事件驱动的网络应用程序框架,支持快速地开发可维护的高性能的面向协议的服务器和客户端 Java 网络编程 早期的 Java API 只支持由本地系统套接字库提供的所谓的阻塞函数, ...
- ChatGPT访问互联网,不神秘了
我测试了一下,它其实调用了微软必应的api,搜索了关键词而已 比如我问它:https://twitter.com/elonmusk 马斯克最近在忙什么 它的回答是: 近期,马斯克在做的一些事情包括: ...
- 极限五分钟,在宝塔中用 Docker 部署升讯威在线客服系统
我在业余时间开发维护了一款免费开源的升讯威在线客服系统,也收获了许多用户.对我来说,只要能获得用户的认可,就是我最大的动力. 最近客服系统成功经受住了客户现场组织的压力测试,获得了客户的认可. 客户组 ...
- OpenShift 与 OpenStack:让云变得更简单
OpenShift 与 OpenStack 都是在 2010.2011 年左右创建的,用于构建可扩展云平台的开源技术,两者都用于在混合云环境中构建可扩展系统.从历史来看,OpenStack 的存在时间 ...
- 将文件从windows格式改为linux格式
1.使用notepad++软件转换 notepad++官方下载地址 使用notepad++打开文件---编辑---文档格式转换---转为unix---上传至linux 2.set ff vim 文件, ...
- maven 强制使用本地仓库
pom 文件添加如下内容: <repositories> <repository> <id>alimaven</id> <name>aliy ...
- PySpark 报错 java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver
解决方案: mv mysql-connector-java-8.0.20.jar $SPARK_HOME/jars/ 驱动文件mysql-connector-java-8.0.20.jar是从mave ...
- 08_N叉树的层序遍历
N叉树的层序遍历 给定一个 N 叉树,返回其节点值的层序遍历.(即从左到右,逐层遍历). 树的序列化输入是用层序遍历,每组子节点都由 null 值分隔(参见示例). 示例 1: 输入:root = [ ...
- 基于python的租房网站-房屋出租租赁系统(python+django+vue)
该项目是基于python/django/vue开发的房屋租赁系统/租房平台,作为本学期的课程作业作品.欢迎大家提出宝贵建议. 功能介绍 平台采用B/S结构,后端采用主流的Python+Django进行 ...