Альтернативный подход, полезный для токенизации длинных строк, состоит в том, чтобы построить единое регулярное выражение омнибуса, а затем использовать именованные группы для идентификации токенов. Требуется небольшая настройка, но фаза распознавания помещается в C/native-код и занимает всего один проход, поэтому он может быть довольно эффективным.Например:
import re
tokens = {
'a': ['andy', 'alpha', 'apple'],
'b': ['baby']
}
def create_macro_re(tokens, flags=0):
"""
Given a dict in which keys are token names and values are lists
of strings that signify the token, return a macro re that encodes
the entire set of tokens.
"""
d = {}
for token, vals in tokens.items():
d[token] = '(?P<{}>{})'.format(token, '|'.join(vals))
combined = '|'.join(d.values())
return re.compile(combined, flags)
def find_tokens(macro_re, s):
"""
Given a macro re constructed by `create_macro_re()` and a string,
return a list of tuples giving the token name and actual string matched
against the token.
"""
found = []
for match in re.finditer(macro_re, s):
found.append([(t, v) for t, v in match.groupdict().items() if v is not None][0])
return found
Заключительный шаг, запустив его:
macro_pat = create_macro_re(tokens, re.I)
print find_tokens(macro_pat, 'this is a string of baby apple Andy')
macro_pat
заканчивается соответствующая:
re.compile(r'(?P<a>andy|alpha|apple)|(?P<b>baby)', re.IGNORECASE)
И вторая строка выводит список кортежей, каждый дает маркер и фактическая строка, сопоставленная с токеном:
[('b', 'baby'), ('a', 'apple'), ('a', 'Andy')]
В этом примере показано, как список токенов можно скомпилировать в одно регулярное выражение, и это может быть эффективно выполнено против строки за один проход.
Оставшееся не показано - одна из его сильных сторон: способность определять токены не только через строки, но и через регулярные выражения. Поэтому, если нам нужны альтернативные варианты написания токена b
, например, нам не нужно их перечислять исчерпывающе. Нормальных регулярных выражений достаточно. Скажем, мы хотели также признать «babby» как токен b
. Мы могли бы сделать 'b': ['baby', 'babby']
, как и раньше, или мы можем использовать регулярное выражение, чтобы сделать то же самое: 'b': ['babb?y']
. Или 'bab+y'
, если вы хотите также включить произвольные внутренние символы 'b'.
Elasticsearch - действительно путь! – alfasin
Любые хорошие документы или ссылки, которые вы можете поделиться, которые помогут мне начать быстро без особых проблем? – python
Может ли даже elasticsearch создать набор совпадающих слов из ввода терминов 10000 (2000 X ~ 5)? Тем не менее - идея перевернутого словаря ниже, чтобы отфильтровать поисковик mach на 10000 слов до ключевых терминов 2000 года. – jsbueno