Python:难以过滤掉包含某些子串的字符串

Ala*_*anH 3 python list

我有一个我想要过滤的字符串列表.如果它包含单词blahblah,那么我想保留它.我是第一种方式尝试过的,而且我一遍又一遍地查看我的代码,但我不知道为什么它会保留一些字符串,其中没有"blahblah"这个词.但是,我尝试了第二种方式,它起作用了.我很好奇为什么第一种方法不起作用.

第一种方法:

for item in my_list:
    if 'blahblah' not in item:
        my_list.remove(item)
Run Code Online (Sandbox Code Playgroud)

第二种方法:

my_new_list = []
for m in my_list:
    if 'blahblah' in m:
        my_new_list.append(p)
Run Code Online (Sandbox Code Playgroud)

第二种方法给了我想要的东西.我仔细检查了从第二个列表生成的列表的每个元素.

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

ozg*_*gur 5

在迭代它时不应修改列表,因为您将丢失其中元素的实际位置.您可以使用列表推导来进行过滤:

my_list[:] = [s for s in my_list if 'blahblah' in s]
Run Code Online (Sandbox Code Playgroud)

[:]使我们能够进行就地更改,而不是先创建新过滤的列表并将其分配回来my_list.

如果你想坚持传统for,你可以做到以下几点:

for item in my_list[:]:
    if 'blahblah' not in item:
        my_list.remove(item)  
Run Code Online (Sandbox Code Playgroud)

至于你的第二个问题,你的代码可能运行速度更快的.remove()需要O(n),你会收集你的对象在一个新的列表,而不是从现有的一个移除其他人消除了.但是,这一次,它将需要更多的内存空间,因为您将创建一个新的单独列表.


Ana*_*mar 5

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


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

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

my_new_list = [m for m in my_list if 'blahblah' in m]
Run Code Online (Sandbox Code Playgroud)

如果要更改my_list位置,可以[:]在作业的左侧使用-

my_list[:] = [m for m in my_list if 'blahblah' in m]
Run Code Online (Sandbox Code Playgroud)

演示 -

>>> my_list = ['blahblah','asdas']
>>> [m for m in my_list if 'blahblah' in m]
['blahblah']
Run Code Online (Sandbox Code Playgroud)

两种方法之间的时间比较(如评论中所要求的) -

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
Run Code Online (Sandbox Code Playgroud)