首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >检查列表的元素是否存在于另一个列表的元素中

检查列表的元素是否存在于另一个列表的元素中
EN

Stack Overflow用户
提问于 2013-02-01 20:45:11
回答 3查看 832关注 0票数 2

我在列表上遇到了一些麻烦。所以,基本上,我有一个清单:

代码语言:javascript
代码运行次数:0
运行
复制
a=["Britney spears", "red dog", "\xa2xe3"]

我还有另一个列表,看起来像这样:

代码语言:javascript
代码运行次数:0
运行
复制
b = ["cat","dog","red dog is stupid", "good stuff \xa2xe3", "awesome Britney spears"]

我想要做的是检查a中的元素是否是b中某个元素的一部分--如果是的话,将它们从b的元素中删除。所以,我希望b看起来像这样:

代码语言:javascript
代码运行次数:0
运行
复制
b = ["cat","dog","is stupid","good stuff","awesome"]

在2.7.x中,实现这一点的最具pythonic风格的方法是什么?

我假设我可以循环检查每个元素,但我不确定这是否非常有效-我有一个大小约为50k的列表(b)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-02-01 20:51:21

我想我会在这里使用正则表达式:

代码语言:javascript
代码运行次数:0
运行
复制
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 ']

这样,正则表达式引擎就可以针对备选方案列表优化测试。

这里有一堆替代方案来展示不同的正则表达式的行为。

代码语言:javascript
代码运行次数:0
运行
复制
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']
票数 4
EN

Stack Overflow用户

发布于 2013-02-01 21:03:19

好吧,我不知道这还算不算蟒蛇,因为reduce被流放到python3的functools,总得有人说一句:

代码语言:javascript
代码运行次数:0
运行
复制
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]

更快的是

代码语言:javascript
代码运行次数:0
运行
复制
[reduce(lambda acc, n: acc.replace(n, '') if n in acc else acc, a, x).strip() for x in b]

但随着可读性的降低,我认为它变得越来越不像pythonic了。

这里有一个处理transferred dogcatcher的案例。我借用了mgilson的正则表达式,但我认为这是可以的,因为它非常琐碎:-):

代码语言:javascript
代码运行次数:0
运行
复制
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提取到一个命名函数中。

票数 2
EN

Stack Overflow用户

发布于 2013-02-01 20:48:51

嗯,最简单的方法是直接的列表理解,只要a很小,它甚至是一种非常有效的方法。

代码语言:javascript
代码运行次数:0
运行
复制
b = [i for i in b if i not in a]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14646606

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档