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

时间:2016-11-24 16:21:24

标签: python list list-comprehension

最近我遇到了这个问题:

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

["/test/fruit/banana","/test/animal/penguin","/test/fruit/pineapple"]

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

exclude_list=["pen","banana"]

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

["/test/fruit/apple","/test/fruit/pineapple","/test/animal/python"]

或者如果exclude_list是: for item in exclude_list: for name in (process_list): if item in name: process_list.remove(name)

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

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 ]  

当然这不起作用,因为不允许在使用@interface NSURLRequest (InvalidSSLCertificate) + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host; + (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host; @end 循环迭代它时从列表中删除元素。代码只删除了第一个匹配,然后停止了。

然后我想出了另一个列表的方法:

[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];

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

6 个答案:

答案 0 :(得分: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']

关于你的陈述:

  

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

您可以迭代列表副本:

 for item in list(exclude_list):  # OR, for item in exclude_list[:]:
 #              ^-- Creates new copy ----------------------------^           

答案 1 :(得分:4)

此外,您还可以使用正则表达式,例如

import re

pattern = '(' + ('|').join(exclude_list) + ')'
list(filter(lambda l : re.search(pattern,l) == None, process_list)) #filter will return iterator in case if you use python 3 

答案 2 :(得分:2)

使用os.path.basename获取路径名的基本名称,使用内置功能all检查exclude_list中是否包含基本名称。

import os 

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"]

# Case 1
exclude_list=["apple","python"]

l = [s for s in process_list 
        if all(item not in os.path.basename(s) for item in exclude_list)]

print(l)
['/test/fruit/banana', '/test/animal/penguin']

# Case 2
exclude_list=["pen","banana"]

l = [s for s in process_list 
        if all(item not in os.path.basename(s) for item in exclude_list)]

print(l)
['/test/fruit/apple', '/test/fruit/pineapple', '/test/animal/python']

答案 3 :(得分:1)

[line for line in lines if not any(word in line for word in words)]

答案 4 :(得分:1)

实现目标的另一种方法如下:

[item for item in process_list if not any(exc in item.split('/')[-1] for exc in exclude_list)]

<强>输出:

>>> [item for item in process_list if not any(exc in item.split('/')[-1] for exc in exclude_list)]
['/test/fruit/banana', '/test/animal/penguin']

答案 5 :(得分:0)

如果你想直接使用process_list和列表理解而没有任何有趣的行为,你应该使用副本,它是这样创建的:process_list [:]

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"]
exclude_list=["apple","python"]
process_list = [x for x in  process_list[:] if not any(y in x for y in exclude_list)]