在python中搜索列表中的字符串

时间:2011-05-06 07:34:09

标签: python string list substring

您好 我有一个包含邮件地址的字符串。例如(user@foo.bar.com) 我有一个只包含域名的列表('bar.com','stackoverflow.com')等。

如果它包含我的字符串域,我想搜索列表。现在我正在使用像这样的代码

if tokens[1].partition("@")[2] in domainlist:

令牌[1]包含邮件地址,域列表包含域。 但正如您所见,tokens[1].partition("@")[2]的结果将返回foo.bar.com,但我的列表中包含域bar.com。 如何使if语句返回true?它应该非常快,因为每秒都有数百个邮件地址

5 个答案:

答案 0 :(得分:4)

它应该像这样工作:

if any(tokens[1].endswith(domain) for domain in domainlist): 

答案 1 :(得分:2)

如果速度真的是你的问题,你可以研究像Aho-Corasick这样的方法。有很多可用的实现,例如esmre / esm http://code.google.com/p/esmre/

正如@Riccardo Galli所指出的,简单的字符串匹配会产生一些误报,因此您可以先使用esmre进行尝试,将正则表达式添加到索引中,例如index.enter("(^|\.){0}$".format(domain))

答案 2 :(得分:1)

首先,将domainlist设为一组。检查是否包含某些内容会更快。

其次,将所有“超级域名”添加到此集合中,例如“foo.bar.com”的“bar.com”。

domainlist = ['foo.bar.com', 'bar2.com', 'foo3.bar3.foobar.com']
domainset = set()
for domain in domainlist:
    parts = domain.split('.')
    domainset.update('.'.join(parts[i:]) for i in xrange(len(parts)-1))

#domainset is now:
set(['bar.com',
     'bar2.com',
     'bar3.foobar.com',
     'foo.bar.com',
     'foo3.bar3.foobar.com',
     'foobar.com'])

现在你可以测试了

if tokens[1].partition("@")[2] in domainset:

答案 3 :(得分:1)

数百个邮件地址不应成为问题。以下是单行:

any(domain.endswith(d) for d in MY_DOMAINS)

在这里,您可以user,sep,domain = address.rpartition('@')。否则,对于"B@tm4n"@something.com等电子邮件地址,您的当前方法将失败,这些地址根据http://tools.ietf.org/html/rfc5322

有效

如果性能成为一个因素,您可以使用Trie(一种数据结构)。如果表现仍然是一个因素,你可以使用其他技巧。

上面介绍了您正在检查的域中的每个元素,因此如果列表中有1000个域,则需要为每个电子邮件地址执行1000次查找。如果这是一个问题,您可以执行此操作以实现每次查找O(1)(您还可能希望确保不检查超过5个后缀,以保护自己免受恶意制作的电子邮件地址)。

MY_DOMAINS = set(MY_DOMAINS)

def suffixes(domain):
    """
        suffixes('foo.bar.com') -yields-> ['foo.bar.com', 'bar.com', 'com']
    """
    while True:
        yield domain
        parts = domain.split('.',1)
        if len(parts>1)
            domain = parts[1]
        else:
            break
def isInList(address):
    user,sep,domain = address.rpartition('@')
    return any(suffix in MY_DOMAINS for suffix in suffixes(domain))

答案 4 :(得分:1)

与其他答案相反,这里'foo.com'也不会与'@ y.afoo.com'相匹配

def mailInDomains(mail,domains):

    for domain in domainList:
        dLen = len(domain)
        if mail[-dLen:]==domain and mail[-dLen-1] in ('.','@'):
            return True

    return False