在python中,我想从列表中删除任何包含在所谓的“黑名单”中找到的子字符串的字符串。
例如,假定列表A为以下内容:
A = [ 'cat', 'doXXXg', 'monkey', 'hoBBBrse', 'fish', 'snake']
清单B是:
B = ['XXX', 'BBB']
我如何获得列表C:
C = [ 'cat', 'monkey', 'fish', 'snake']
我玩过各种正则表达式和列表理解的组合,但似乎无法正常工作。
您可以将黑名单加入一个表达式中:
import re
blacklist = re.compile('|'.join([re.escape(word) for word in B]))
然后过滤出匹配的单词:
C = [word for word in A if not blacklist.search(word)]
模式中的单词会被转义(这样,.
其他元字符就不会被这样处理,而是视为文字字符),并加入一系列|
替代项中:
>>> '|'.join([re.escape(word) for word in B])
'XXX|BBB'
演示:
>>> import re
>>> A = [ 'cat', 'doXXXg', 'monkey', 'hoBBBrse', 'fish', 'snake']
>>> B = ['XXX', 'BBB']
>>> blacklist = re.compile('|'.join([re.escape(word) for word in B]))
>>> [word for word in A if not blacklist.search(word)]
['cat', 'monkey', 'fish', 'snake']
这应该胜过任何显式的成员资格测试,尤其是随着黑名单中单词数量的增加:
>>> import string, random, timeit
>>> def regex_filter(words, blacklist):
... [word for word in A if not blacklist.search(word)]
...
>>> def any_filter(words, blacklist):
... [word for word in A if not any(bad in word for bad in B)]
...
>>> words = [''.join([random.choice(string.letters) for _ in range(random.randint(3, 20))])
... for _ in range(1000)]
>>> blacklist = [''.join([random.choice(string.letters) for _ in range(random.randint(2, 5))])
... for _ in range(10)]
>>> timeit.timeit('any_filter(words, blacklist)', 'from __main__ import any_filter, words, blacklist', number=100000)
0.36232495307922363
>>> timeit.timeit('regex_filter(words, blacklist)', "from __main__ import re, regex_filter, words, blacklist; blacklist = re.compile('|'.join([re.escape(word) for word in blacklist]))", number=100000)
0.2499098777770996
上面的测试针对1000个随机单词(长度为3-20个字符)列表中的10个随机列入黑名单的短单词(2-5个字符),正则表达式快50%。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句