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的更多相关文章

  1. [LeetCode] Arithmetic Slices II - Subsequence 算数切片之二 - 子序列

    A sequence of numbers is called arithmetic if it consists of at least three elements and if the diff ...

  2. 【夯实Mysql基础】MySQL性能优化的21个最佳实践 和 mysql使用索引

    本文地址 分享提纲: 1.为查询缓存优化你的查询 2. EXPLAIN 你的 SELECT 查询 3. 当只要一行数据时使用 LIMIT 1 4. 为搜索字段建索引 5. 在Join表的时候使用相当类 ...

  3. 2-1 Linux 操作系统及常用命令

    根据马哥linux初级视频 2-1.2-2来编辑 1. GUI与CLI GUI: Graphic User Interface CLI: Command Line Interface 注:在Windo ...

  4. Fedora 21 安装 Nvidia 驱动以及失败后的补救方法

    在 Linux 桌面系统下玩了这么久,大部分时间都是使用 Ubuntu,偶尔使用一下 Fedora.我的电脑中安装有多个 Linux 发行版,见这里<在同一个硬盘上安装多个Linux发行版及Fe ...

  5. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  6. CSharpGL(21)用鼠标拾取、拖拽VBO图元内的点、线或本身

    CSharpGL(21)用鼠标拾取.拖拽VBO图元内的点.线或本身 效果图 以最常见的三角形网格(用GL_TRIANGLES方式进行渲染)为例. 在拾取模式为GeometryType.Point时,你 ...

  7. ABP(现代ASP.NET样板开发框架)系列之21、ABP展现层——Javascript函数库

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之21.ABP展现层——Javascript函数库 ABP是“ASP.NET Boilerplate Project ...

  8. C#开发微信门户及应用(21)-微信企业号的消息和事件的接收处理及解密

    在上篇随笔<C#开发微信门户及应用(19)-微信企业号的消息发送(文本.图片.文件.语音.视频.图文消息等)>介绍了有关企业号的消息发送,官方特别声明消息是不用加密发送的.但是在回调的服务 ...

  9. [LeetCode] Arithmetic Slices 算数切片

    A sequence of number is called arithmetic if it consists of at least three elements and if the diffe ...

  10. 【转】MySQL性能优化的最佳21条经验

    文章转自: http://blog.csdn.net/waferleo/article/details/7179009 今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关 ...

随机推荐

  1. 朋友们,就在今天,JDK 21,它终于带着重磅新特性正式发布了!

    你好呀,我是歪歪. 朋友们,好消息,好消息,重磅好消息. 从今年年初就一直在喊的具有革命性.未来性.开创新纪元的 JDK 21 按照官方的时间计划表,今天终于是要正式 GA 了: https://op ...

  2. Nacos 1.2.1 集群搭建(二)MySQL、cluster 配置

    三台虚机的IP地址被DHCP重分了一下1.MySQL 配置 先建一个 nacos_config 数据库 将SQL执行(方法很多,选自己喜欢的就行) 2.修改 application.propertie ...

  3. JupyterLab 桌面版 !!!

    JupyterLab 是广受欢迎的 Jupyter Notebook「新」界面.它是一个交互式的开发环境,可用于 notebook.代码或数据,因此它的扩展性非常强. 用户可以使用它编写 notebo ...

  4. 当谈论 React hook,我们究竟说的是什么?

    这个标题很大,但是落点很小,只是我,一个开发者在学习和使用 hooks 中的一点感受和总结. React hook 的由来 React hook 的由来,其实也可以看作是前端技术不断演进的结果. 在 ...

  5. 【k8s】基本原理学习

    k8s基本原理 https://www.cnblogs.com/BlueBlueSea/p/16908601.html 深入理解Kubernetes网络 深入理解Kubernetes的pod网络 参考 ...

  6. JSP 学习笔记 | 三、EL 表达式简述

    前文:JSP 学习笔记 | 二.JSP 脚本 & 案例实现 & 缺点分析 前文:JSP 学习笔记 | 一.JSP 原理理解 概述 EL(全称Expression Language )表 ...

  7. 打破 Serverless 落地边界,阿里云 SAE 发布 5 大新特性

    微服务场景,开源自建真的最快最省最稳的?复杂性真的会成为 Kubernetes 的"致命伤"吗?企业应用容器化,一定得过 K8s 这座"独木桥"吗?Server ...

  8. springboot+vue实现 下载服务端返回的文件功能

    开发中会遇到,通过浏览器下载服务器端返回的文件功能,本文使用springboot+vue实现该功能. 后端代码: 注:后端返回的文件名遇到中文就会乱码,一直也没得到很好的解决方案,最后就统一返回1.x ...

  9. Webpack Vue瘦身,感受快到飞起的加载速度!

    症结 在利用webpack脚手架搭建vue项目后,往往最终打包的.js和.css文件过于庞大,造成首次加载的时候白屏时间过长,影响用户体验,下图为未经任何优化直接npm run build之后的情况: ...

  10. appium(二)安装(Android)

    一.安装Appium-desktop 1.官网下载安装包: http://appium.io/