Поиск строки в списке в Python

1

Привет У меня есть строка, которая содержит адрес электронной почты. Например ([email protected]) И у меня есть список, который содержит только домены ( "bar.com", "stackoverflow.com" ) и т.д.

Я хочу искать список, если он содержит мой строковый домен. Сейчас я использую такой код

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

tokens [1] содержит почтовый адрес, а доменный список содержит домены. Но, как вы видите, результат tokens[1].partition("@")[2] вернет foo.bar.com, но мой список имеет домен bar.com. Как я могу сделать это, если выражение return true? И это должно быть очень быстро, потому что сотни почтовых адресов будут входить в каждую секунду

  • 0
    Использование .partition("@")[2] не удастся для определенных типов адресов электронной почты. См. Stackoverflow.com/questions/5908190/… чтобы узнать, как это сделать.
Теги:
string
list
substring

5 ответов

4
Лучший ответ

Он должен работать следующим образом:

if any(tokens[1].endswith(domain) for domain in domainlist): 
  • 1
    слишком просто, домен 'foo.com' будет совпадать с 'somefoo.com'
  • 0
    Благодарю. Работает так, как я хочу :)
Показать ещё 2 комментария
2

Если вам действительно нужна скорость, вы можете изучить такие методы, как Aho-Corasick. Существует множество реализаций, например esmre/esm http://code.google.com/p/esmre/

Как указано @Riccardo Galli, простое сопоставление строк приведет к некоторым ложным срабатываниям, поэтому сначала вы можете попробовать esmre, добавив в регулярные выражения в индекс, что-то вроде index.enter("(^|\.){0}$".format(domain))

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
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))
1

Сначала сделайте domainlist набор. Будет быстрее проверить, есть ли в нем что-то.

Во-вторых, добавьте все "супердомены" в этот набор, например "bar.com" для "foo.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:

Ещё вопросы

Сообщество Overcoder
Наверх
Меню