python正则表达式否定了一个单词列表?

sim*_*rsh 0 python regex regex-negation

我必须匹配文本中的所有字母数字单词.

>>> import re
>>> text = "hello world!! how are you?"
>>> final_list = re.findall(r"[a-zA-Z0-9]+", text)
>>> final_list
['hello', 'world', 'how', 'are', 'you']
>>>
Run Code Online (Sandbox Code Playgroud)

这很好,但是我还有一些词可以否定,即不应该在我的最终列表中的词.

>>> negate_words = ['world', 'other', 'words']
Run Code Online (Sandbox Code Playgroud)

这是一个糟糕的方式

>>> negate_str = '|'.join(negate_words)
>>> filter(lambda x: not re.match(negate_str, x), final_list)
['hello', 'how', 'are', 'you']
Run Code Online (Sandbox Code Playgroud)

但是如果可以改变我的第一个正则表达式模式以考虑否定这些单词,我可以保存一个循环.我发现对字符的否定,但我有言辞否定,我也在其他问题中找到正则表达式,但这也无济于事.

可以使用python re完成吗?

更新

我的文字可以跨越几条线条.此外,negate_words列表也可能很长.

考虑到这一点,正在使用正则表达式来完成这样的任务,首先纠正?有什么建议??

Ray*_*ger 6

我不认为使用正则表达式有一种干净的方法.我能找到的最接近的地方有点丑陋而且不完全是你想要的:

>>> re.findall(r"\b(?:world|other|words)|([a-zA-Z0-9]+)\b", text)
['hello', '', 'how', 'are', 'you']
Run Code Online (Sandbox Code Playgroud)

为什么不使用Python的集合呢?它们非常快:

>>> list(set(final_list) - set(negate_words))
['hello', 'how', 'are', 'you']
Run Code Online (Sandbox Code Playgroud)

如果订单很重要,请参阅下面的@glglgl回复.他的列表理解版本非常易读.这是使用itertools的快速但不太可读的等价物:

>>> negate_words_set = set(negate_words)
>>> list(itertools.ifilterfalse(negate_words_set.__contains__, final_list))
['hello', 'how', 'are', 'you']
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用re.finditer在单个传递中构建单词列表:

>>> result = []
>>> negate_words_set = set(negate_words)
>>> result = []
>>> for mo in re.finditer(r"[a-zA-Z0-9]+", text):
    word = mo.group()
    if word not in negate_words_set:
         result.append(word)

>>> result
['hello', 'how', 'are', 'you']
Run Code Online (Sandbox Code Playgroud)

  • 值得一提的是,单词顺序将会丢失. (5认同)
  • `[如果我不在negate_words_set中,我在final_list中为i] (2认同)