我正在尝试编写一个函数来搜索str的substr,考虑到编写奇怪字母的不同可能性,例如丹麦语中的æ,ø,å。例如,你可以搜索'Ålborg',如果有的话,函数将返回true,在str中说'Aalborg'。
以下功能有效,但性能难以忍受。你会建议什么来改善表现?
def danish_tolerating_search(substr, str):
'''Figure out if substr is in str, taking into account
possible deviations in writing letters æ, ø, å.
æ <-> ae a ea
ø <-> oe o
å <-> aa a o
'''
# normalize input
substr = substr.lower().replace('aa',u'å')
str = str.lower()
# normalized recursive search
# TODO fix perfomance
def s(substr, str):
if str.find(substr) >= 0: return True
if substr.find(u'æ') >= 0:
if s(substr.replace(u'æ','ae', 1), str): return True
elif s(substr.replace(u'æ', 'a', 1), str): return True
elif s(substr.replace(u'æ','ea', 1), str): return True
if str.find(u'æ') >= 0:
if s(substr, str.replace(u'æ','ae', 1)): return True
elif s(substr, str.replace(u'æ', 'a', 1)): return True
elif s(substr, str.replace(u'æ','ea', 1)): return True
if substr.find(u'ø') >= 0:
if s(substr.replace(u'ø','oe', 1), str): return True
elif s(substr.replace(u'ø', 'o', 1), str): return True
if str.find(u'ø') >= 0:
if s(substr, str.replace(u'ø','oe', 1)): return True
elif s(substr, str.replace(u'ø', 'o', 1)): return True
if substr.find(u'å') >= 0:
if s(substr.replace(u'å','aa', 1), str): return True
elif s(substr.replace(u'å', 'a', 1), str): return True
elif s(substr.replace(u'å', 'o', 1), str): return True
if str.find(u'å') >= 0:
if s(substr, str.replace(u'å','aa', 1)): return True
elif s(substr, str.replace(u'å', 'a', 1)): return True
elif s(substr, str.replace(u'å', 'o', 1)): return True
return False
return s(substr, str)
答案 0 :(得分:3)
我认为你应该完全消除递归。例如,您可以决定输入字符串的“正常形式”,相应地转换它们(即替换那些“含糊不清的”字符)而不是完成find
和replace
的所有操作。简单
return substring in string_
另请注意,您不需要同时调用find
和replace
,后者就足够了。如果找不到搜索字符串,则替换只是不会替换任何内容。
答案 1 :(得分:3)
尝试
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import re
def danish_tolerating_search(search, content):
search = search.lower()
content = content.lower()
variants = {
u'a': u'[aæå]',
u'o': u'[oøå]',
u'ae': u'(?:ae|æ)',
u'ea': u'(?:ea|æ)',
u'aa': u'(?:aa|å)',
u'oe': u'(?:oe|ø)',
u'\\å': u'(?:[oå]|aa?)',
u'\\ø': u'(?:ø|oe?)',
u'\\æ': u'(?:æ|ae?|ea)',
}
search = re.escape(search)
search = re.sub(ur'[ae]a|[ao]e?|\\[åøæ]', lambda m: variants[m.group(0)], search)
return re.search(search, content) is not None
我没有测试它的性能,因为OP没有发布任何内容。我只是假设正则表达式引擎比以递归方式调用OP的s()
并执行大量.find
和.replace
更优化。
这里,搜索字符串中的关键字母被正则表达式中可能的等价类替换,例如, Ålborg
变为(?:[oå]|aa?)lb[oøå]rg
。这个正则表达式应该包括@ 101100提到的所有可能的变体,相当于Ålborg
(ålbørg“或”ålbårg“或”aalborg“或”aalbørg“或”aalbårg“或”alborg“或”albørg“或”albårg“)评论)。然后根据上下文搜索正则表达式。
答案 2 :(得分:1)
这是解析器的经典示例。阅读lex和yacc之类的内容,你不需要他们所有的功能,但原则仍然适用。
之后,使用python re模块匹配相应的正则表达式。如果您需要更多功能,请使用pyparsing库。
def danish_tolerating_search(substr, str):
'''Figure out if substr is in str, taking into account
possible deviations in writing letters æ, ø, å.
æ <-> ae a ea
ø <-> oe o
å <-> aa a o
for all of these combinations replace with appropriate regex as in example
'''
substring = substring.lower().replace('aa', '[ae]{1,2}')
string = string.lower()
re.search(substring, string)