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

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

刪除切片中的元素

刪除切片中的元素

Go
一只名叫tom的貓 2023-03-29 15:17:46
Go 不提供任何高級函數來從切片中刪除元素。我編寫了一個函數,以此處通常建議的方式從切片中刪除給定值,但它產生了意想不到的結果。package mainimport "fmt"type Area struct {    Cells [2][]uint8}func main() {    var area1 Area    area1.Cells[1] = []uint8 {5, 6, 7}    area2 := area1    area1.Cells[1] = removeValueFromCell(area1.Cells[1], 6)    fmt.Println(area1.Cells[1])    fmt.Println(area2.Cells[1])}func removeValueFromCell(cell []uint8, value uint8) []uint8{    var res = cell    for i := 0; i < len(cell); i++ {        if cell[i] == value {            res = append(cell[:i], cell[i+1:]...)        }    }    return res}該程序輸出:[5 7] <- as expected[5 7 7] <- why not [5 6 7] or [5 7] ?
查看完整描述

1 回答

?
湖上湖

TA貢獻2003條經驗 獲得超2個贊

切片值只是標頭,指向后備數組。切片頭只包含指針。所以當你復制一個切片值時,副本也會指向同一個后備數組。因此,如果您通過原始切片標頭更改支持數組,則副本也會觀察到更改。

這就是你的情況。你分配area1area2.?單元格是一個切片數組。因此將復制數組,其中包含切片標頭,因此將復制切片標頭。切片頭包含指向支持數組的指針,支持數組不會被復制。

所以只有一個支持數組來保存[5, 6, 7]元素。然后調用removeValueFromCell(),它會修改這個后備數組:

Before:
[5,?6,?7]
After:
[5,?7,?7]

因為該元素6已被刪除,所以切片的其余部分(元素[7])被復制以代替被刪除的元素。

然后您將這個新的切片標頭(正確地只包含 2 個元素)分配給area1.Cells[1].

但是 slice 值area2.Cells[1]指向同一個后備數組,并且由于您沒有觸及這個 slice 值,它的長度仍然是3,所以它會看到所有后備數組都更改了元素:[5, 7, 7]

另請注意,您的 實現removeValueFromCell()是錯誤的,因為如果可移動元素在切片中多次列出,它的行為將不正確。這樣做的原因是因為當您刪除一個元素時,后續元素的索引會移動(減少 1),但您的循環變量不會考慮到這一點。最容易處理的是使用向下循環。


查看完整回答
反對 回復 2023-03-29
  • 1 回答
  • 0 關注
  • 144 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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