亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從 Golang 中的切片中刪除

從 Golang 中的切片中刪除

Go
精慕HU 2023-06-19 17:46:05
我有以下測試打印原始輸入切片(過濾后),沒有已刪除的元素,但最后有一個額外的元素使輸入切片具有相同的長度,即使過濾后它應該是更短。我怎樣才能避免有一個“輸出切片”?(以正確的方式打印,包含正確的元素,具有預期的長度和容量)為什么我嘗試“刪除就地”導致“輸入切片”的長度與過濾過程之前的長度相同?為什么“輸入切片”的長度與我應用過濾過程之前的長度相同?如何進行刪除操作以更改“輸入切片”的長度?這是代碼:這是測試執行的輸出:$ go test -v -run TestFoo=== RUN? ?TestFooOriginal (PRE) slice[{1 FooCat 6.046602879796196} {2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904}]342019/05/31 12:53:30 Loop ID 0Original (POST) slice[{2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904} {3 FooCat 6.645600532184904}]34Filtered element{1 FooCat 6.046602879796196}Output slice[{2 FooCat 9.405090880450125} {3 FooCat 6.645600532184904}]24--- PASS: TestFoo (0.00s)PASSok? ? ? git.openenergi.net/scm/flex/service/common? 0.008s更新“作為指針的輸入切片”好的,假設我想處理原始輸入切片,即沒有副本或輸出切片。為什么以下代碼在注釋的代碼行中引發運行時恐慌?(?pointedInSl[inLen-1] = FooItem{})為什么打印的切片(應用函數后)在其末尾包含 2 個相同的項目?如何刪除最后一個冗余元素?為什么應用函數后切片的長度仍然與應用函數前的切片長度相同?如何使原始切片縮小 1(即輸出長度 = 原始長度 - 1)?
查看完整描述

2 回答

?
慕田峪7331174

TA貢獻1828條經驗 獲得超13個贊

當你有一個int類型的變量時,你想寫一個函數來遞增它的值,你該怎么做?您要么將指針傳遞給變量,要么返回必須分配給原始變量的增量值。

例如(在Go Playground上試試):

func inc(i int) int { i++; return i }


var i int = 2

inc(i)

fmt.Println(i) // This will be 2

在上面的代碼中,您將i其inc()遞增并返回其值。原件i當然不會變,i里面inc()只是一個副本,獨立于原件i。要更改原件,您必須評估返回值:


i = inc(i)

或者首先使用指針(在Go Playground上嘗試):


func inc(i *int) { *i++ }


var i int = 2

inc(&i)

fmt.Println(i) // This will be 3

切片也是如此。如果您想要/必須修改切片標頭(這是一個數據指針、長度和容量,請參閱參考資料reflect.SliceHeader),您要么必須將指針傳遞給該切片(不是很常見),要么必須返回修改后的新切片您必須在呼叫者處分配的標頭。這是更常用的解決方案,這也是內置函數遵循的方法append()。

當您切片時,(例如someslice[min:max]),新切片將與原始切片共享支持數組。這意味著如果您修改新切片的元素,原始切片也會觀察到這些更改。因此,如果您從新切片中刪除一個元素并將元素復制到被刪除元素的位置,則原始切片的最后一個元素仍將在那里,它被原始切片“覆蓋”。通常的做法是將最后一個元素置零,以便垃圾收集器可以回收它的內存,如果它是指針類型(或“類似”如切片、映射或通道)。

  • 我怎樣才能避免有一個“輸出切片”?(以正確的方式打印,包含正確的元素,具有預期的長度和容量)

正如這個答案中所述:您必須將一個指針傳遞給您的切片,并修改 中的指向值FindAndRemoveFromFooSlice(),因此您不必返回新切片。

  • 為什么我嘗試“刪除就地”導致“輸入切片”的長度與過濾過程之前的長度相同?

你從來沒有修改過原始切片,你傳遞了它所以制作了一個副本,并且在內部FindAndRemoveFromFooSlice()你只能修改副本(但你甚至沒有修改副本)。你返回一個新的切片,但你沒有分配它,所以原來的切片(頭)是完整的。

  • 為什么“輸入切片”的長度與我應用過濾過程之前的長度相同?如何進行刪除操作以更改“輸入切片”的長度?

前兩個問題回答了這個問題。


查看完整回答
反對 回復 2023-06-19
?
德瑪西亞99

TA貢獻1770條經驗 獲得超3個贊

最小工作代碼示例(帶有注釋以提供一些上下文):


// use a pointer for the input slice so then it is changed in-place

func FindAndRemoveFromFooSliceInPlace(iFilter int, inSl *[]FooItem) *FooItem {

? ? pointedInSl := *inSl // dereference the pointer so then we can use `append`

? ? inLen := len(pointedInSl)

? ? for idx, elem := range pointedInSl {

? ? ? ? if elem.Id == iFilter {

? ? ? ? ? ? log.Printf("Loop ID %v", idx)


? ? ? ? ? ? // check these docs: https://github.com/golang/go/wiki/SliceTricks#delete

? ? ? ? ? ? pointedInSl = append(pointedInSl[:idx], pointedInSl[idx+1:inLen]...)

? ? ? ? ? ? pointedInSl = pointedInSl[:inLen-1]

? ? ? ? ? ? *inSl = pointedInSl // assigning the new slice to the pointed value before returning


? ? ? ? ? ? return &elem

? ? ? ? }

? ? }

? ? return nil

}


查看完整回答
反對 回復 2023-06-19
  • 2 回答
  • 0 關注
  • 161 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號