首页 新闻 会员 周边 捐助

立刻向前滑动补位,这就是“塌缩”

0
[已解决问题] 解决于 2025-09-07 07:54
letter = ['A','B','C','D','D','D']
for i in letter:
     if i == 'D':
          letter.remove(i)

print(letter)
输出结果是
问题补充:
把列表看成一个抽屉柜,for-loop 的迭代器就是一把从左往右逐个拉开的钥匙:
原始抽屉(索引)
0 1 2 3 4 5
A B C D D D
循环变量 i 并不真正保存元素,而是按序号 0→1→2→3→4→5 去“拉开”抽屉。
当你在某一步把某个抽屉 抽掉(remove) 后,后面的抽屉会立刻向前滑动补位,这就是“塌缩”。
逐步演示:
  1. i=0 → 'A',不是 D,不动。
  2. i=1 → 'B',不是 D,不动。
  3. i=2 → 'C',不是 D,不动。
  4. i=3 → 第一个 D
    执行 remove('D'),列表变成
    0 1 2 3 4
    A B C D D
    后面所有元素整体左移一格。
  5. 循环继续,下一条索引是 i=4
    此时 4 号抽屉已经是最后一个 D,而原来在 3 号位置的第二个 D 被跳过了!
  6. i=5 超出范围,循环结束。
最终剩了一个 D,就是被跳过的那只抽屉。
核心一句话:
“迭代器按‘位置’走,列表按‘内容’删;位置一旦前移,后面元素就顶替,导致某些位置再也访问不到。”
_java_python的主页 _java_python | 小虾三级 | 园豆:984
提问于:2025-09-07 07:50
< >
分享
最佳答案
0
  1. 列表的真实布局
    CPython 的 list 是一个指针数组(PyObject *[])。
    删除元素时先把目标指针 DECREF,再把右边所有指针 memmove 向前一格,最后把数组长度减 1——O(n) 时间完成“物理左移”。
    1. 同样是“连续数组”实现
      C/C++ 的 std::vector、Rust 的 Vec、Go 的 slice、Java 的 ArrayList
      删除后都会把后续元素 memmove 向前;
      如果你用下标++ 的方式遍历,也会得到完全相同的“跳过”现象。
      示例(C++):
      cpp
      复制
      for (size_t i = 0; i < v.size(); ++i) if (v[i] == 'D') v.erase(v.begin()+i); // 同样会漏
       
       
      Java 数组 == 定长块;想可变长,就用 ArrayList(或自己封装拷贝逻辑),“定长”只是让“删除”操作不存在,从而避免了塌缩场景

       

      如果你换成 ArrayList(可变长,底层同样是连续数组),照样会塌缩:
      java
      复制
      List<String> list = new ArrayList<>(Arrays.asList("A","B","C","D","D","D"));
      for (int i = 0; i < list.size(); i++)
          if ("D".equals(list.get(i)))
              list.remove(i);   // 删后 size--,后续元素前移,i++ 会跳过一位
      System.out.println(list); // [A, B, C, D] —— 剩一个 D
      现象与 Python 完全一致。

       

       
_java_python | 小虾三级 |园豆:984 | 2025-09-07 07:53
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册