0

假设我有一个关键字列表和一个句子列表:

keywords = ['foo', 'bar', 'joe', 'mauer']
listOfStrings = ['I am frustrated', 'this task is foobar', 'mauer is awesome']

如何遍历我的 listOfStrings 并确定它们是否包含任何关键字...必须完全匹配!这样:

>>for i in listOfStrings:
    for p in keywords:
       if p in i:
         print i

>> 'mauer is awesome'

(因为 'foobar' 与 'foo' 或 'bar' 不完全匹配,所以函数应该只捕获 'foobar' 如果它是关键字)

我怀疑 re.search 可能是方式,但我无法弄清楚如何循环列表,使用变量而不是使用 re 模块的逐字表达式。
谢谢

4

3 回答 3

1

完全匹配的一个更好的主意是将关键字存储在一个集合中

keywords = {'foo', 'bar', 'joe', 'mauer'}
listOfStrings = ['I am frustrated', 'this task is foobar', 'mauer is awesome']

[s for s in listOfStrings if any(w in keywords for w in s.split())]

这只测试每个单词listOfStrings一次。您的方法(或使用正则表达式)查看每个关键字中listOfStrings每个单词。随着关键字数量的增加,这将非常低效。

于 2013-05-12T22:29:21.613 回答
0

如果用正则表达式元字符包围一个单词,\b然后将其用作正则表达式,则需要在单词边界上进行匹配:

http://www.regular-expressions.info/wordboundaries.html

元字符 \b 是类似于插入符号和美元符号的锚。它在称为“单词边界”的位置匹配。这个匹配是零长度的。

此外,请确保您的 python 正则表达式使用re.IGNORECASEhttp ://docs.python.org/2/library/re.html#re.IGNORECASE

并且不要忘记,\在语言的字符串解析器和正则表达式引擎本身中,它都可能被视为元字符,这意味着它必须加倍为\\b.

于 2013-05-12T22:25:28.117 回答
0

您可以将句子分解为单词,然后检查每个关键字是否是关键字,而不是检查每个关键字是否包含在字符串中的任何位置。这样你就不会有部分匹配的问题。

在这里,RE_WORD定义为一个单词边界,至少一个字符,然后是另一个单词边界的正则表达式。您可以使用re.findall()来查找字符串中的所有单词。re.compile()预编译正则表达式,以便不必为每一行从头开始解析。

frozenset()是一种有效的数据结构,可以回答“给定单词在冻结集中吗?”这个问题。比扫描一长串关键字并尝试每一个关键字更快。

#!/usr/bin/env python2.7

import re

RE_WORD = re.compile(r'\b[a-zA-Z]+\b')

keywords = frozenset(['foo', 'bar', 'joe', 'mauer'])
listOfStrings = ['I am frustrated', 'this task is foobar', 'mauer is awesome']

for i in listOfStrings:
    for word in RE_WORD.findall(i):
        if word in keywords:
            print i
            continue
于 2013-05-12T22:53:11.453 回答