slices in Go 1.21

来源:https://www.cnblogs.com/lianshuiwuyi/archive/2023/10/08/17748064.html
-Advertisement-
Play Games

Go 1.21中新增的 slices包中提供了很多與切片相關的函數,適用於任意類型的切片。 本文內容來自官方文檔 BinarySearch 函數簽名如下: func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) Bina ...


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: 戀水無意



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文在這裡。 本教程為 Go 程式員提供了使用Protocol buffer的基本介紹。 本教程使用proto3向 Go 程式員介紹如何使用 protobuf。通過創建一個簡單的示例應用程式,它向你展示瞭如何: 在.proto中定義消息格式 使用protocol buffer編譯器 使用Go pro ...
  • 在本文中,我們深入探討了Go語言中數組的各個方面。從基礎概念、常規操作,到高級技巧和特殊操作,我們通過清晰的解釋和具體的Go代碼示例為讀者提供了全面的指南。無論您是初學者還是經驗豐富的開發者,這篇文章都將助您更深入地理解和掌握Go數組的實際應用。 關註公眾號【TechLeadCloud】,分享互聯網 ...
  • Sleuth 簡介 隨著業務的發展,系統規模變得越來越大,微服務拆分越來越細,各微服務間的調用關係也越來越複雜。客戶端請求在後端系統中會經過多個不同的微服務調用來協同產生最後的請求結果,幾平每一個請求都會形成一個複雜的分散式服務調用鏈路,在每條鏈路中任何一個依賴服務出現延遲超時或者錯誤都有可能引起整 ...
  • go語言-Go環境搭建 下載 https://golang.org/dl/ 切換root許可權 su root 進入用戶列表 cd /usr/local/ 解壓縮 tar -zxvf go1.13.linux-amd64.tar.gz 設置go環境變數 vi /etc/profile export G ...
  • 基於java智能物流管理系統設計與實現,可適用於校園物流管理系統,物流配送系統,快遞物流管理,物流追蹤系統,物流系統,物流運輸系統,javaweb物流系統,springboot物流管理系統,javaweb智能物流系統等等; ...
  • 來源:www.cnblogs.com/tjstep/p/15256463.html mybatis作為一個輕量級的ORM框架,應用廣泛,其上手使用也比較簡單;一個成熟的框架,必然有精巧的設計,值得學習。 在使用mybatis框架時,在sql語句中獲取傳入的參數有如下兩種方式: ${paramName ...
  • 今天主要說說如何通過自定義註解的方式,在 Spring Boot 中來實現 AOP 切麵統一列印出入參日誌。小伙伴們可以收藏一波。 廢話不多說,進入正題! 一、先看看切麵日誌輸出效果 在看看實現方法之前,我們先看下切麵日誌輸出效果咋樣: 從上圖中可以看到,每個對於每個請求,開始與結束一目瞭然,並且打 ...
  • 1 SPI簡介 1.1 SPI(Service Provider Interface) 本質:將介面實現類的全限定名配置在文件中,並由服務載入器讀取配置文件,載入實現類。這樣可以在運行時,動態為介面替換實現類。 java SPI:用來設計給服務提供商做插件使用的。基於策略模式來實現動態載入的機制。我 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...