[英]check if element of list is present in elements of another list
我在使用列表时遇到了麻烦。 因此,基本上,我有一个列表:
a=["Britney spears", "red dog", "\xa2xe3"]
我还有另一个列表,看起来像:
b = ["cat","dog","red dog is stupid", "good stuff \xa2xe3", "awesome Britney spears"]
我想要做的是检查a
中的元素是否是b
中某个元素的一部分 - 如果是,则从b
的元素中删除它们。 所以,我希望b
看起来像:
b = ["cat","dog","is stupid","good stuff","awesome"]
什么是最pythonic(2.7.x)的方式来实现这一目标?
我假设我可以循环检查每个元素,但我不确定这是非常有效的 - 我有一个大小为50k的列表( b
)。
我想我在这里使用正则表达式:
import re
a=["Britney spears", "red dog", "\xa2xe3"]
regex = re.compile('|'.join(re.escape(x) for x in a))
b=["cat","dog","red dog is stupid", "good stuff \xa2xe3", "awesome Britney spears"]
b = [regex.sub("",x) for x in b ]
print (b) #['cat', 'dog', ' is stupid', 'good stuff ', 'awesome ']
这样,正则表达式引擎可以针对替代项列表优化测试。
这是一堆替代方法,以显示不同的正则表达式的行为。
import re
a = ["Britney spears", "red dog", "\xa2xe3"]
b = ["cat","dog",
"red dog is stupid",
"good stuff \xa2xe3",
"awesome Britney spears",
"transferred dogcatcher"]
#This version leaves whitespace and will match between words.
regex = re.compile('|'.join(re.escape(x) for x in a))
c = [regex.sub("",x) for x in b ]
print (c) #['cat', 'dog', ' is stupid', 'good stuff ', 'awesome ', 'transfercatcher']
#This version strips whitespace from either end
# of the returned string
regex = re.compile('|'.join(r'\s*{}\s*'.format(re.escape(x)) for x in a))
c = [regex.sub("",x) for x in b ]
print (c) #['cat', 'dog', 'is stupid', 'good stuff', 'awesome', 'transfercatcher']
#This version will only match at word boundaries,
# but you lose the match with \xa2xe3 since it isn't a word
regex = re.compile('|'.join(r'\s*\b{}\b\s*'.format(re.escape(x)) for x in a))
c = [regex.sub("",x) for x in b ]
print (c) #['cat', 'dog', 'is stupid', 'good stuff \xa2xe3', 'awesome', 'transferred dogcatcher']
#This version finally seems to get it right. It matches whitespace (or the start
# of the string) and then the "word" and then more whitespace (or the end of the
# string). It then replaces that match with nothing -- i.e. it removes the match
# from the string.
regex = re.compile('|'.join(r'(?:\s+|^)'+re.escape(x)+r'(?:\s+|$)' for x in a))
c = [regex.sub("",x) for x in b ]
print (c) #['cat', 'dog', 'is stupid', 'good stuff', 'awesome', 'transferred dogcatcher']
好吧,我不知道这是否算作pythonic了,因为reduce
被放到python3的functools
中,所以有人不得不在表上放一个衬里:
a = ["Britney spears", "red dog", "\xa2xe3"]
b = ["cat","dog","red dog is stupid", "good stuff \xa2xe3", "awesome Britney spears"]
b = [reduce(lambda acc, n: acc.replace(n, ''), a, x).strip() for x in b]
会更快
[reduce(lambda acc, n: acc.replace(n, '') if n in acc else acc, a, x).strip() for x in b]
但随着可读性的降低,我认为它的pythonic越来越少。
这是一个处理transferred dogcatcher
案件的人。 我借用了mgilson的正则表达式,但我认为它没关系,因为它非常简单:-):
def reducer(acc, n):
if n in acc:
return re.sub('(?:\s+|^)' + re.escape(n) + '(?:\s+|$)', '', acc)
return acc
b = [reduce(reducer, a, x).strip() for x in b]
我将lambda
提取到一个命名函数以提高可读性。
好吧,最简单的方法就是直接理解列表,只要a
很小,它甚至是相当有效的方法。
b = [i for i in b if i not in a]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.