go語(yǔ)言切片去重的3種方式
go語(yǔ)言中的切片是使用非常頻繁的一個(gè)數(shù)據(jù)結(jié)構(gòu),對(duì)于他的去重,我們可以有以下3種方式
1. 切片slice去重
利用map的key不能重復(fù)的特性+append函數(shù) 一次for循環(huán)搞定
這個(gè)模式時(shí)間復(fù)雜度最低,效率最高, 如果go版本大于1.21推薦使用這種方式的泛型參數(shù)版本
// 改進(jìn)版的slice去重 func UniqueSliceInt64(ss []int64) []int64 { newSS := make([]int64, 0) // 返回的新切片 m1 := make(map[int64]byte) //用來(lái)去重的臨時(shí)map for _, v := range ss { if _, ok := m1[v]; !ok { m1[v] = 1 newSS = append(newSS, v) } } return newSS }
泛型參數(shù)版本,需要go版本大于1.21 否則不能使用泛型參數(shù)
// 切片去重升級(jí)版 泛型參數(shù) 利用map的key不能重復(fù)的特性+append函數(shù) 一次for循環(huán)搞定 func Unique[T cmp.Ordered](ss []T) []T { size := len(ss) if size == 0 { return []T{} } newSlices := make([]T, 0) //這里新建一個(gè)切片,大于為0, 因?yàn)槲覀儾恢烙袔讉€(gè)非重復(fù)數(shù)據(jù),后面都使用append來(lái)動(dòng)態(tài)增加并擴(kuò)容 m1 := make(map[T]byte) for _, v := range ss { if _, ok := m1[v]; !ok { //如果數(shù)據(jù)不在map中,放入 m1[v] = 1 // 保存到map中,用于下次判斷 newSlices = append(newSlices, v) // 將數(shù)據(jù)放入新的切片中 } } return newSlices }
2. 切片去重
利用map的key不能重復(fù)的特性 2次for循環(huán)
下面這個(gè)使用了泛型參數(shù)
//go版本大于1.21的情況,可以使用泛型參數(shù) // 切片去重 泛型參數(shù) 利用map的key不能重復(fù)的特性 2次for循環(huán) func Unique1[T cmp.Ordered](ss []T) []T { size := len(ss) if size == 0 { return []T{} } // 這個(gè)地方利用了map數(shù)據(jù)的key不能重復(fù)的特性,將切片的值當(dāng)做key放入map中,達(dá)到去重的目的 m1 := make(map[T]byte) for i := 0; i < size; i++ { m1[ss[i]] = 1 } // 創(chuàng)建一個(gè)切片,長(zhǎng)度為去重后的數(shù)據(jù)長(zhǎng)度 newSS := make([]T, len(m1)) idx := 0 for key := range m1 { // 循環(huán)map, 將key放入到切片中 newSS[idx] = key idx++ } return newSS }
cmp.Ordered泛型參數(shù)約束接口參考 注意上面的泛型參數(shù)約束 cmp.Ordered 是一個(gè)專門用于泛型類型約束的接口定義, 需要go版本大于1.21才能使用
type Ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string }
3. 切片去重
雙層for循環(huán)模式
這種方式方式直觀,但是時(shí)間復(fù)雜度較高!
// 切片去重 雙層for循環(huán)模式 func Unique0(ss []int64) (newSS []int64) { newSS = make([]int64, 0) for i := 0; i < len(ss); i++ { repeat := false for j := i + 1; j < len(ss); j++ { if ss[i] == ss[j] { repeat = true break } } if !repeat { newSS = append(newSS, ss[i]) } } return }
總結(jié)
對(duì)于golang的切片去重,效率最高的方式為map+append函數(shù)的方式,因?yàn)樗麄兊臅r(shí)間復(fù)雜度是最低的,對(duì)于go版本大于1.21的推薦使用泛型參數(shù)的切片去重,這樣一個(gè)函數(shù)就可以解決所有類型的切片去重問(wèn)題,高效精簡(jiǎn)!
到此這篇關(guān)于go語(yǔ)言切片去重的3種方式 的文章就介紹到這了,更多相關(guān)go語(yǔ)言切片去重內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談Go語(yǔ)言多態(tài)的實(shí)現(xiàn)與interface使用
如果大家系統(tǒng)的學(xué)過(guò)C++、Java等語(yǔ)言以及面向?qū)ο蟮脑?,相信?yīng)該對(duì)多態(tài)不會(huì)陌生。多態(tài)是面向?qū)ο蠓懂牣?dāng)中經(jīng)常使用并且非常好用的一個(gè)功能,它主要是用在強(qiáng)類型語(yǔ)言當(dāng)中,像是Python這樣的弱類型語(yǔ)言,變量的類型可以隨意變化,也沒(méi)有任何限制,其實(shí)區(qū)別不是很大2021-06-06淺談golang 中time.After釋放的問(wèn)題
這篇文章主要介紹了淺談golang 中time.After釋放的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05一文帶你了解Golang中select的實(shí)現(xiàn)原理
select是go提供的一種跟并發(fā)相關(guān)的語(yǔ)法,非常有用。本文將介紹?Go?語(yǔ)言中的?select?的實(shí)現(xiàn)原理,包括?select?的結(jié)構(gòu)和常見(jiàn)問(wèn)題、編譯期間的多種優(yōu)化以及運(yùn)行時(shí)的執(zhí)行過(guò)程2023-02-02Golang使用CGO與Plugin技術(shù)運(yùn)行加載C動(dòng)態(tài)庫(kù)
這篇文章主要介紹了Golang使用CGO與Plugin技術(shù)運(yùn)行加載C動(dòng)態(tài)庫(kù),Golang?程序在運(yùn)行時(shí)加載C動(dòng)態(tài)庫(kù)的技術(shù),跳過(guò)了Golang項(xiàng)目編譯階段需要鏈接C動(dòng)態(tài)庫(kù)的過(guò)程,提高了Golang項(xiàng)目開(kāi)發(fā)部署的靈活性2022-07-07讓go程序以后臺(tái)進(jìn)程或daemon方式運(yùn)行方法探究
本文探討了如何通過(guò)Go代碼實(shí)現(xiàn)在后臺(tái)運(yùn)行的程序,最近我用Go語(yǔ)言開(kāi)發(fā)了一個(gè)WebSocket服務(wù),我希望它能在后臺(tái)運(yùn)行,并在異常退出時(shí)自動(dòng)重新啟動(dòng),我的整體思路是將程序轉(zhuǎn)為后臺(tái)進(jìn)程,也就是守護(hù)進(jìn)程(daemon)2024-01-01Go語(yǔ)言實(shí)現(xiàn)socket實(shí)例
這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)socket的方法,實(shí)例分析了socket客戶端與服務(wù)器端的實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02