我正在评估一长串句子,看看它们是否包含州名并用dict映射它们,这就是我想出的代码 - 它的速度很慢。该如何正确完成?
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
我不知道如何提前创建绑定版本 - 我可以创建一组并使用它吗?
为了清楚起见,我想知道,对于我所拥有的每个句子,该句子中包含的最多一个匹配的州名或缩写。我的困难在于不知道如何预先组装一个可用的" bound" "整个单词"的状态字符串的版本匹配。这导致我在内循环中使用re.compile
。
答案 0 :(得分:2)
你一遍又一遍地编译所有正则表达式(N次!其中N是句子数)。 re.compile
不是一个快速的操作,所以这就是造成痛苦的原因。您可以初始化它们的字典,以便按状态查找它们:
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 :(得分:1)
我建议您构建一个匹配所有状态的正则表达式。然后,您可以对每个sentance执行单个,更复杂的正则表达式搜索,并从结果中提取匹配状态:
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
然后使用已编译模式的方法一样快。
答案 2 :(得分:0)
由于您不想一遍又一遍地编译正则表达式(n^2
次而不是n
次......)。更改for循环的顺序并在中间编译正则表达式会更有效:
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