首页 > 其他分享 >slices in Go 1.21

slices in Go 1.21

时间:2023-10-08 09:38:23浏览次数:30  
标签:slices int fmt Println func Go 1.21 main

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
}

孟斯特

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意


标签:slices,int,fmt,Println,func,Go,1.21,main
From: https://www.cnblogs.com/lianshuiwuyi/p/17748064.html

相关文章

  • Golang HOT100 做题记录
     LeetCode热题100  1.两数之和题目大意:给出一个数字的数[]num,一个目标值target。在数组中,找出两数之和为目标值的下标,任意输出一个答案。例子:num[]={0,2,3,4,2},target=4,输出:[]int{0,3}注意点:1.不能重复,如上不能为[]int{1,1},2.注意数组中重复数字处理 ......
  • Go - Remove values from a slice
    Totakeoutthefirstelementoftheslice:numbers:=[]int{3,14,159,26,53,58}numbers=numbers[1:]//removeelement0To takeoutthelastelementoftheslice:numbers:=[]int{3,14,159,2......
  • Go - Insert values into a slice
    Thereisnobuilt-infunctionforinsertion,butyoucanstilluseappendforthetask.Let’ssayyouwanttoinsertthenumber1000betweenelementsatindex2and3,whichareints159and26,respectively:numbers:=[]int{3,14,159,......
  • Go - Defining Metadata for Struct Fields
    Problem: Youwanttodefinemetadatatodescribethestructfields.Solution: Usestructtagstodefinemetadataandthereflectpackagetoaccessthetags. Oneverycommonplaceyoufindthisisinthejsonpackage:typePersonstruct{......
  • CF1856B Good Arrays
    题意简述:给定一个序列\(a\),我们定义一个序列\(b\)是好的当且仅当对于\(1\dotsn\)内的每一个\(i\),\(a_i\neqb_i\)且\(\sum_{i=1}^na_i=\sum_{i=1}^nb_i\)(\(a_i\),\(b_i\)均为正整数)。现在有\(T\)组数据,每组数据给定\(n\)和序列\(a\),判断是否存在一个合法的序......
  • Go 项目代码布局
    Go项目代码布局目录Go项目代码布局一、Go语言“创世项目”结构1.1src目录结构三个特点二、Go项目布局演进2.1演进一:Go1.4版本删除pkg这一中间层目录并引入internal目录2.2演进二:Go1.6版本增加vendor目录2.3演进三:Go1.13版本引入go.mod和go.sum三、现在Go......
  • Go 基础之基本数据类型
    Go基础之基本数据类型目录Go基础之基本数据类型一、整型1.1平台无关整型1.1.1基本概念1.1.2分类有符号整型(int8~int64)无符号整型(uint8~uint64)1.2平台相关整型1.2.1基本概念1.2.2注意点1.2.3获取三个类型在目标运行平台上的长度1.3整型的溢出问题1.3.1什么是整形溢出?1.......
  • GO语言基础之基本运算符
    GO语言基础之基本运算符目录GO语言基础之基本运算符一、运算符内置运算符:二、算术运算符三、关系运算符四、逻辑运算符五、位运算符六、赋值运算符一、运算符作用:运算符用于在程序运行时执行数学或逻辑运算。内置运算符:Go语言内置的运算符有:算术运算符关系运算符逻辑运......
  • Go基础之指针
    Go语言中的指针目录Go语言中的指针一、Go语言中的指针介绍1.1指针介绍1.2基本语法1.3声明和初始化1.4Go指针的3个重要概念1.4.1指针地址(PointerAddress)1.4.2指针类型(PointerType)1.4.3指针取值(PointerDereferencing)1.5获取指针的地址和解引用1.6传递指针给函数1.7指......
  • Go 复合数据类型之结构体与自定义类型
    Go复合数据类型之结构体与自定义类型目录Go复合数据类型之结构体与自定义类型一、类型别名和自定义类型1.1类型定义(TypeDefinition)简单示例1.2类型别名简单示例1.3类型定义和类型别名的区别二、结构体2.1结构体介绍2.2结构体的定义2.3定义一个空结构体2.3.1空结构体介......