2 回答
TA贡献1842条经验 获得超12个赞
在内部,切片就像一个包含三个元素的结构:
一个支持数组
后备数组的大小,可以访问为
cap(slice)
切片的长度,可以访问为
len(slice)
在您的循环运行之前,支持数组 fora
是[0, 1, 2, 3]
with cap(a) == len(a) == 4
。
当您a
使用以下代码进行修改时:
a = append(a[:i], a[i+1:]...)
a
由于新长度小于容量,因此新值共享原始的后备数组。因此,在第一次迭代中修改后,支持数组现在包含[1, 2, 3, 3]
with len(a) == 3
。数组中的最后一个元素通过正常的切片操作是不可见的,但保留其旧值。
在第二次迭代中,切片再次缩短,因此支持数组现在[1, 3, 3, 3]
是len(a) == 2
。
现在,当循环运行时,range
表达式只计算一次,因此无论您在循环中进行什么更改,它始终会导致 4 次迭代。它还将从同一个支持数组返回结果,这解释了您看到的数字。
TA贡献1802条经验 获得超4个赞
问题是a您在迭代时正在修改(删除元素),因此结果可能有点......令人惊讶。我的猜测是,你的第一个删除后,a是在内存中类似的东西:[1 2 3 3],所以a[2]是3和你的第二个删除后,a是类似的东西在内存:[1 3 3 3]等a[3]是3。
因此,我的第一个建议是更改代码以使用传统for循环而不是范围,并且i仅在您不删除某些内容时才增加:
package main
import "fmt"
func main() {
a := []int{0, 1, 2, 3}
for i := 0; i < len(a); {
v := a[i]
fmt.Printf("i: %d v: %d\n", i, v)
fmt.Println("before", a)
if v%2 == 0 {
// delete a[i]
a = append(a[:i], a[i+1:]...)
} else {
i++
}
fmt.Println("after", a, "\n")
}
fmt.Println("final", a)
}
这是输出:
i: 0 v: 0
before [0 1 2 3]
after [1 2 3]
i: 0 v: 1
before [1 2 3]
after [1 2 3]
i: 1 v: 2
before [1 2 3]
after [1 3]
i: 1 v: 3
before [1 3]
after [1 3]
final [1 3]
我的第二个建议是反转循环(从末尾迭代)以避免递增/递减的“特殊情况”:
package main
import "fmt"
func main() {
a := []int{0, 1, 2, 3}
for i := len(a) - 1; i >= 0; i-- {
v := a[i]
fmt.Printf("i: %d v: %d\n", i, v)
fmt.Println("before", a)
if v%2 == 0 {
// delete a[i]
a = append(a[:i], a[i+1:]...)
}
fmt.Println("after", a, "\n")
}
fmt.Println("final", a)
}
这是输出:
i: 3 v: 3
before [0 1 2 3]
after [0 1 2 3]
i: 2 v: 2
before [0 1 2 3]
after [0 1 3]
i: 1 v: 1
before [0 1 3]
after [0 1 3]
i: 0 v: 0
before [0 1 3]
after [1 3]
final [1 3]
- 2 回答
- 0 关注
- 212 浏览
添加回答
举报