2015-09-12 2 views
1

Я оцениваю длинный список предложений, чтобы увидеть, включают ли они имена состояний и сопоставляют их с dict, и это код, который я придумал - это очень медленно. Как это должно быть сделано правильно?Как эффективно выполнять поиск регулярных выражений из набора python

 for sent in sentences: #set of sentences.upper() 
      for state in stateset: #set of state abbrev's and names in .upper() 
       boundst = re.compile(r'\b%s\b' % state, re.I) 
       if re.search(boundst, sent): 
        sentstatedict[sent] = state 
        break 

Я не знаю, как создать связанные версии загодя - могу ли я создать их набор и использовать?

Чтобы было ясно, я хотел узнать, для каждого предложения, которое у меня было, не более одного совпадающего имени или аббревиатуры, содержащихся в этом предложении. Моя трудность заключалась в том, что я не знал, как предварительно собрать список используемых «привязанных» версий строк состояния для соответствия «всего слова». Это привело меня к тому, что во внутреннем цикле было re.compile.

ответ

2

Вы компилируете все регулярные выражения снова и снова (N раз !, где N - количество предложений). re.compile не является быстрой операцией, поэтому это вызывает боль. Вы можете инициализировать Dict из них, так что вы можете посмотреть их государством:

re_lookup = { 
    state: re.compile(r'\b%s\b' % state, re.I) 
    for state in stateset 
} 

for sent in sentences: 
    for state in stateset: 
     if re.search(re_lookup[state], sent): 
      sentstatedict[sent] = state 
      break 
+1

. 'Re.compile' кэширует шаблоны, которые вы передаете ему (вы называете это явно или полагаетесь на неявную компиляцию одной из функций поиска верхнего уровня, таких как' re.search', с шаблоном строки). – Blckknght

+0

По какой-то причине (назовите мою непитонику) словари словарей здесь имеют для меня больше смысла, чем циклы в циклах в функциях. – Xodarap777

+0

Это оставляет правильный перерыв. В штате всего 100 элементов, поэтому исходный цикл не повредит. – Xodarap777

0

Поскольку вы не хотите компилировать регулярное выражение снова и снова (n^2 раз вместо n раз ...). Это будет более эффективно изменить порядок для петель и компилировать регулярное выражение в промежутке между:

for state in stateset:    
    boundst = re.compile(r'\b%s\b' % state, re.I) # compile the regex once (at most) per each state 
     for sent in sentences: 
      if re.search(boundst, sent): 
       sentstatedict[sent] = state 
       break 
+0

У вас немного лучше :), но НЕ по той причине, что вы заявляете! Вы по-прежнему будете компилировать одно регулярное выражение для каждого состояния. – BrianO

+0

@BrianO, пожалуйста, просветите меня :) почему? – alfasin

+0

Поскольку внешний цикл будет проходить через каждое состояние, верно? Перерыв только ломается до следующей итерации предложения. – Xodarap777

1

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

pattern = r"\b({})\b".format("|".join(stateset)) 
for sent in sentences: 
    match = re.search(pattern, sent, re.I) 
    if match: 
     sentstatedict[sent] = match.group(1) 

Я не утруждая re.compile, потому что вся регулярные выражения метода, которые принимают шаблоны строк кэширует скомпилированной внутри. Поэтому поиск с помощью той же строки шаблона должен быть таким же быстрым, как и вызывать compile, а затем использовать методы скомпилированного шаблона.

+0

Plz plz plz изменить 'if match is not None:' to: 'if match:' - у меня больно глаза ...: D – alfasin

+0

Вы имеете в виду 'if match'. «Если не совпадение» было тем, как я изначально написал его, и я, хотя это было уродливо (доказательство того, что вкусы могут отличаться), поэтому я изменил его на «если совпадение« Нет »в какой-то момент, прежде чем реверсировать логику теста (когда я понял, что мне не нужно ничего делать в неудачном матче). Я изменил его снова, так как я согласен, что 'if match' лучше, чем' if match is not None' (если предположить, что никакое другое допустимое значение для 'match' не будет ложным). – Blckknght

+0

Да, 'если матч' - сказал, что это больно моим глазам ... :) – alfasin

Смежные вопросы