删除列表中没有出现在另一个列表中的子串的项目的优雅方法

Arc*_*rus 8 python list-comprehension list

最近我遇到了这个问题:

假设有一个我想要处理的内容列表:

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"]
Run Code Online (Sandbox Code Playgroud)

我想用其他列表排除某些内容,例如:

exclude_list=["apple","python"]
Run Code Online (Sandbox Code Playgroud)

在我对其应用exclude_list之后,process_list应该是这样的(任何包含子的process_list项:

["/test/fruit/banana","/test/animal/penguin","/test/fruit/pineapple"]
Run Code Online (Sandbox Code Playgroud)

或者如果exclude_list是: exclude_list=["pen","banana"]

应用过滤器后,process_list应为此:

["/test/fruit/apple","/test/fruit/pineapple","/test/animal/python"]
Run Code Online (Sandbox Code Playgroud)

所以我最初尝试的是:

for item in exclude_list:
    for name in (process_list):
        if item in name:
            process_list.remove(name)
Run Code Online (Sandbox Code Playgroud)

当然这不起作用,因为for不允许在使用循环迭代它时从列表中删除元素.代码只删除了第一个匹配,然后停止了.

那么我想出了另一个列表的方法:

deletion_list=[] #Track names that need to be deleted
for item in exclude_list:
    for name in (process_list):
        if item in name:
            deletion_list.append(name)
# A list comprehension
process_list=[ x for x in process_list if x not in deletion_list ]  
Run Code Online (Sandbox Code Playgroud)

它有效,但我的胆量告诉我可能有更优雅的方式.现在需要另一个列表来存储需要删除的名称.有任何想法吗?

Moi*_*dri 14

您可以使用过滤器列表推导表达式all():

# Here: `p` is the entry from `process_list`
#       `e` is the entry from `exclude_list`

>>> [p for p in process_list if all(e not in p for e in exclude_list)]                              
['/test/fruit/banana', '/test/animal/penguin']
Run Code Online (Sandbox Code Playgroud)

关于你的陈述:

当然这不起作用,因为不允许在使用for循环迭代它时从列表中删除元素.代码只删除了第一个匹配,然后停止了.

您可以迭代列表副本:

 for item in list(exclude_list):  # OR, for item in exclude_list[:]:
 #              ^-- Creates new copy ----------------------------^           
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢`...如果所有(不是在......)中更清楚地传达语义,但我认为这主要是品味问题. (4认同)