slices in Go 1.21

这篇具有很好参考价值的文章主要介绍了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) < 0cmp(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来比较s1s2的元素。从索引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

Deletes中删除元素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

DeleteFuncs中删除函数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返回vs中第一次出现的索引,如果不存在则返回-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
}

slices in Go 1.21

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意文章来源地址https://www.toymoban.com/news/detail-710550.html


到了这里,关于slices in Go 1.21的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • go 1.21:cmp

    原文在这里 go 1.21 新增 cmp 包提供了与有序变脸比较相关的类型和函数。 定义如下: Ordered 是一个约束,它允许任何有序类型:任何支持 、 = 、 = 、 运算符的类型。如果 Go 的未来版本添加了新的有序类型,这个约束将被修改以包含它们。 请注意,浮点类型可能包含 NaN (

    2024年02月10日
    浏览(43)
  • Go 自学:切片slices

    以下代码展示了两种建立slice的方法。 我们可以使用sort函数给slice排序。 输出为: Type of fruitlist is []string [Apple Tomato Peach Mango Banana] [Apple Tomato Peach] [234 945 465 867 555 666 321] false [234 321 465 555 666 867 945] 以下代码展示了如何根据index从slice中移除指定元素。

    2024年02月11日
    浏览(27)
  • 【Go】Go 语言教程--GO语言切片(Slice)(十四)

    往期回顾: Go 语言教程–介绍(一) Go 语言教程–语言结构(二) Go 语言教程–语言结构(三) Go 语言教程–数据类型(四) Go 语言教程–语言变量(五) Go 语言教程–GO语言常量(六) Go 语言教程–GO语言运算符(七) Go 语言教程–GO条件和循环语句(八) Go 语言教程

    2024年02月16日
    浏览(37)
  • Go 切片Slice的长度len与容量cap

    0x00 简介 Go 语言之旅示例 切片的长度与容量 切片拥有长度和容量。 切片的长度是它所包含的元素个数。 切片的容量是从它的第一个元素开始数,到其底层数组元素末尾的个数。 切片 s 的长度和容量可通过表达式 len(s) 和 cap(s) 来获取。 package main import \\\"fmt\\\" func main() {     

    2024年02月09日
    浏览(32)
  • 使用go mod tidy命令出现go.mod file indicates go 1.21, but maximum supported version is 1.19,如何解决

    使用git拉取代码Golang代码到本地后,利用VS Code打开项目后,看到go.mod报红,现象如下图所示:` 这个问题是当前使用的go版本与git clone拉取下来的项目的go.mod所用的go版本不一致导致的: 在项目中打开一个terminal,查看当前安装的go版本是否与go.mod的第二行的声明一致:如下图

    2024年02月06日
    浏览(34)
  • Go 中 slice 的 In 功能实现探索

    之前在知乎看到一个问题:为什么 Golang 没有像 Python 中 in 一样的功能?于是,搜了下这个问题,发现还是有不少人有这样的疑问。 补充:本文写于 2019 年。GO 现在已经支持泛型,而且新增了一个 slices 包,已经支持了 Contains 方法。 今天来谈谈这个话题。 in 是一个很常用的

    2024年01月19日
    浏览(32)
  • Go 语言中高效切片拼接和 GO 1.22 提供的新方法

    在 Go 语言中,切片拼接是一项常见的操作,但如果处理不当,可能会导致性能问题或意外的副作用。 本文将详细介绍几种高效的切片拼接方法,包括它们的优缺点以及适用场景。 在 Go 中,切片是一种动态数组,常用于存储和处理一系列相同类型的数据。 在实际应用中,我

    2024年01月19日
    浏览(34)
  • 力扣日记1.21-【回溯算法篇】77. 组合

    日期:2023.1.21 参考:代码随想录、力扣 终于结束二叉树了!听说回溯篇也是个大头,不知道这一篇得持续多久了…… 题目描述 难度:中等 给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1: 输入:n = 4, k = 2 输出:

    2024年01月22日
    浏览(34)
  • Python中的切片(Slice)操作详解

    大家好,这里是果力成,话不多说,学之! 在python学习开发的过程中,我们难免会遇到从某个对象中抽取部分值的情况,对这种经常取指定索引的范围的操作,如果你使用循环的话是可以解决的,但是相对更好的方法而言,此操作是相当繁琐和费事的。 python中的 切片操作 正是专门用

    2024年02月01日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包