V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
omg21
V2EX  ›  Python

list 删除元素后,怎样减循环次数?

  •  
  •   omg21 · 2016-10-30 18:11:56 +08:00 · 3699 次点击
    这是一个创建于 2945 天前的主题,其中的信息可能已经有所发展或是发生改变。
    list1 = ['print','lock','china','page']
    print(len(list1))
    print(list1)
    for i in range(0,len(list1)):
    if list1[i].find('a') != -1:
    list1.pop(i)

    这段代码的本意是查找列表中各元素里有没有字母 a ,如果有 a 就删除这个元素,可是现在发现个问题,删除了以后 len(list1)就减少了,但循环的次数是不减的,所以到了后面就出错了。这样的情况应该怎么改?
    24 条回复    2016-10-31 15:57:07 +08:00
    omg21
        1
    omg21  
    OP
       2016-10-30 18:20:08 +08:00
    list1 = ['print','lock','china','page']
    for sub in list1:
    能不能在这里直接删除元素?
    wannafly
        2
    wannafly  
       2016-10-30 18:20:33 +08:00   ❤️ 1
    正规(高效)的做法应该是在循环中把要删除的元素往前(后)交换, 并同时记录有效元素的最后(起始)索引, 循环结束了一次性删除待删除元素.
    cheneydog
        3
    cheneydog  
       2016-10-30 18:20:57 +08:00   ❤️ 1
    你需要一个新的 list
    264768502
        4
    264768502  
       2016-10-30 18:21:07 +08:00 via Android   ❤️ 1
    list1 = [x for x in list1 if 'a' not in x]
    billion
        5
    billion  
       2016-10-30 18:26:28 +08:00   ❤️ 3
    楼主的代码有一股浓浓的 Java 的味道。
    Python 有更加现代化的写法。

    ![]( https://ooo.0o0.ooo/2016/10/30/5815caa3b24bd.png)
    billion
        6
    billion  
       2016-10-30 18:27:55 +08:00
    https://ooo.0o0.ooo/2016/10/30/5815caa3b24bd.png

    图片又发不出来了吗?
    bingxx
        7
    bingxx  
       2016-10-30 18:40:52 +08:00
    @billion groovy 也可以有优雅的写法。

    def list1 = ['print','lock','china','page']
    def list2 = list1.findAll{it?.contains("a")}
    println(list2)
    omg21
        8
    omg21  
    OP
       2016-10-30 18:46:01 +08:00
    ferran
        9
    ferran  
       2016-10-30 18:48:46 +08:00 via Android
    用迭代器遍历
    Mandown
        10
    Mandown  
       2016-10-30 18:53:23 +08:00
    @billion 回复貌似不资词 markdown
    omg21
        11
    omg21  
    OP
       2016-10-30 18:55:30 +08:00
    @billion 没办法,以前 vb,java 用习惯了,一时半会儿改不过来。
    再追加一个问题,如果 list1 = ['print','lock','china','g'],现在最后一个元素没有 a 了,我想在找到第一个有 a 的元素后不管后边的元素有没有 a 都保留下来,应该怎样做?
    liuxingou
        12
    liuxingou  
       2016-10-30 19:17:15 +08:00
    @omg21

    VB 用习惯是一个比较坑的情景。。。

    如果对内存比较敏感推荐用单向链表而不是 list 。
    luban
        13
    luban  
       2016-10-30 19:20:21 +08:00 via iPhone
    上面说的对,用迭代器。
    java 里面使用 foreach 可以安全的 remove 元素
    luban
        14
    luban  
       2016-10-30 19:21:31 +08:00 via iPhone
    java8 的流使用 filter 过滤出需要的元素也很方便的
    只会 java 路过
    forestyuan
        15
    forestyuan  
       2016-10-30 19:28:55 +08:00
    正确的做法是从后往前删,就没有问题了。
    也就是, for(i = n-1; i >= 0; i --),而不是 for(i = 0; i < n; i ++)
    mooncakejs
        16
    mooncakejs  
       2016-10-30 19:30:44 +08:00
    这种操作应该用 filter 而不是循环去删
    imn1
        17
    imn1  
       2016-10-30 19:46:33 +08:00
    改变思维吧,循环过程中变更 list 长度是错误的思路
    1373569162
        18
    1373569162  
       2016-10-30 19:56:13 +08:00
    @omg21
    1
    2 def f(n, l):
    3 for x in l:
    4 if n in x:
    5 return l[l.index(x):]


    list1 = ['print', 'lock', 'china', 'g']
    list2 = f('a', list1)
    speedcell4
        19
    speedcell4  
       2016-10-30 20:24:20 +08:00
    如果我没理解错的话。。。

    ```python
    list1 = ['print', 'lock', 'china', 'page']

    list2 = [item for item in list1 if item.count('a') == 0]

    print(list2)
    # ['print', 'lock']
    ```
    speedcell4
        20
    speedcell4  
       2016-10-30 20:25:20 +08:00
    或者更直观的

    list1 = ['print', 'lock', 'china', 'page']

    list2 = [item for item in list1 if 'a' not in item]

    print(list2)
    alittletrain
        21
    alittletrain  
       2016-10-30 22:10:39 +08:00
    列表推导最 pythonic
    lrh3321
        22
    lrh3321  
       2016-10-31 11:12:44 +08:00
    还可以使用内置 filter 函数

    list1 = ['print', 'lock', 'china', 'page']

    list2 = filter(lambda item: 'a' not in item,list1)

    print(list2)
    billion
        23
    billion  
       2016-10-31 13:17:31 +08:00
    @omg21 你的第二个需求

    如果你的 list1 里面至少有一个元素包含字母 a, 那么可以这样写:

    list2 = list1[list1.index([x for x in list1 if 'a' in x][0]) + 1 :]

    如果可能所以元素都不含 a,那么建议使用 for 循环。
    iyangyuan
        24
    iyangyuan  
       2016-10-31 15:57:07 +08:00
    倒着来
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2629 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 04:33 · PVG 12:33 · LAX 20:33 · JFK 23:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.