Python:很难过滤出包含特定子字符串的字符串

Python:很难过滤出包含特定子字符串的字符串,python,list,Python,List,我有一个要筛选的字符串列表。如果它包含单词blahblah,那么我想保留它。我尝试了第一种方法,我已经一遍又一遍地检查了我的代码,但我不知道为什么它保留了一些没有“blahblah”这个词的字符串。然而,我尝试了第二种方法,并且成功了。我很好奇为什么第一种方法不起作用 第一种方法: for item in my_list: if 'blahblah' not in item: my_list.remove(item) 第二种方法: my_new_list = [] fo

我有一个要筛选的字符串列表。如果它包含单词
blahblah
,那么我想保留它。我尝试了第一种方法,我已经一遍又一遍地检查了我的代码,但我不知道为什么它保留了一些没有“blahblah”这个词的字符串。然而,我尝试了第二种方法,并且成功了。我很好奇为什么第一种方法不起作用

第一种方法:

for item in my_list:
    if 'blahblah' not in item:
        my_list.remove(item)
第二种方法:

my_new_list = []
for m in my_list:
    if 'blahblah' in m:
        my_new_list.append(p)
第二种方法给了我想要的。我仔细检查了从第二个列表生成的列表中的每个元素

  • 为什么第一种方法不能正确工作
  • 如果我使用第二种方法,如果我有一个非常大的列表,我的代码会运行得更慢吗

  • 您不应该在迭代列表时修改它,因为您将丢失其中元素的实际位置。您可以使用列表理解进行筛选:

    my_list[:] = [s for s in my_list if 'blahblah' in s]
    
    [:]
    使我们能够进行就地更改,而不是先创建一个新筛选的列表,然后将其分配回
    我的列表

    如果您想坚持传统的,可以执行以下操作:

    for item in my_list[:]:
        if 'blahblah' not in item:
            my_list.remove(item)  
    

    至于你的第二个问题,你的代码可能运行得更快,因为
    .remove()
    需要
    O(n)
    ,你可以通过在一个新列表中收集你的对象而不是从现有列表中删除其他对象来消除这个问题。然而,这一次,当您创建一个新的单独列表时,它将需要更多的内存空间

    要回答第一个问题,这是因为当在列表上迭代时,Python内部跟踪当前迭代达到的索引,当您从列表中删除该项时,它将删除元素后的元素索引向左移动1(将这些索引减少1),因此,在下一次迭代中,您可能会跳过一个元素(因为这种移动)


    要回答第二个问题,它应该比删除方法快,因为
    .remove()
    是一个O(n)操作,它需要找到要删除的元素,然后将其删除,相比之下,
    .append()
    会更快

    更快的方法是使用列表理解-

    my_new_list = [m for m in my_list if 'blahblah' in m]
    
    如果您想更改
    my_列表
    ,可以使用作业左侧的
    [:]
    -

    my_list[:] = [m for m in my_list if 'blahblah' in m]
    
    演示-

    >>> my_list = ['blahblah','asdas']
    >>> [m for m in my_list if 'blahblah' in m]
    ['blahblah']
    
    两种方法之间的时间比较(按照评论中的要求)-


    关于列表理解,与创建新列表相比,如果我就地更改列表,速度会有差异吗?我不确定,需要进行测试,但我猜inplace可能比简单地绑定到新名称要慢一点。@AlanH我添加了时间比较,绑定到新名称比inplace更改快一点。
    In [4]: def func1():
       ...:     my_list = ['blahblah' for _ in range(100)]
       ...:     my_list[:] = [m for m in my_list if 'blahblah' in m]
       ...:
    
    In [5]: def func2():
       ...:     my_list = ['blahblah' for _ in range(100)]
       ...:     new_list = [m for m in my_list if 'blahblah' in m]
       ...:
    
    In [6]: %timeit func1()
    100000 loops, best of 3: 13.9 µs per loop
    
    In [7]: %timeit func2()
    100000 loops, best of 3: 13.2 µs per loop
    
    In [8]: %timeit func1()
    100000 loops, best of 3: 13.9 µs per loop
    
    In [9]: %timeit func2()
    100000 loops, best of 3: 13.2 µs per loop
    
    In [10]: %timeit func1()
    100000 loops, best of 3: 13.8 µs per loop
    
    In [11]: %timeit func2()
    100000 loops, best of 3: 13.3 µs per loop