我建议使用字典将您的单词从某种通用形式(可能全部小写)转换为您希望所有项目在数据库中使用的“正确”形式。由于单词的路径很重要,我建议使用包含所有先前规范化路径的元组作为字典的键:
_corrections = {}
def autocorrect(sequence):
normalized = () # used as keys into _autocorrection_dict
corrected = [] # values from _autocorrection_dict
for item in sequence:
if isinstance(item, str):
normalized += (item.lower(),)
corrected = _corrections.setdefault(normalized, corrected + [item])
elif isinstance(item, tuple):
sub_norm = tuple(subitem.lower() for subitem in item)
if normalized + (sub_norm,) not in _corrections:
sub_corrected = ()
for subitem in item:
sub_result = _corrections.setdefault(normalized + (subitem.lower(),),
corrected + [subitem])
sub_corrected += (sub_result[-1],)
_corrections[normalized + (sub_norm,)] = corrected + [sub_corrected]
normalized += (sub_norm,)
corrected = _corrections[normalized]
else:
raise TypeError("Unexpected item type: {}".format(type(item).__name__))
return corrected
该代码的第一部分(if
块)处理简单的字符串值。它应该很容易理解。它建立了一个“标准化”值的元组,这只是迄今为止看到的所有小写字符串。规范化的元组用作_corrections
字典的键,我们在其中存储“正确”的结果。魔术发生在setdefault
调用中,如果一个新条目不存在,它会创建一个新条目。
代码的第二部分(elif
块)是处理元组值的更复杂的部分。首先,我们对元组中的所有字符串进行规范化,并检查我们是否已经有结果(如果我们已经看到这个确切的元组,这可以让我们避免其余的)。如果没有,我们必须检查元组中的每个子项是否有先前保存的结果(如果已经有 和 的条目,那么将["foo", ("BAR", "BAZ")]
有"BAR"
并"BAZ"
更正)。一旦我们为元组中的每个子项找到正确的值,我们就可以将它们放在一起,然后将组合结果添加到字典中。让短路部分工作有点尴尬,但我认为这是值得的。["foo", "bar"]
["foo", "baz"]
这是使用代码的示例会话:
>>> autocorrect(['Abc', ('Def', 'Ghi'), 'Jkl'])
['Abc', ('Def', 'Ghi'), 'Jkl']
>>> autocorrect(['ABC', ("DEF", "GGGG"), "JKL"])
['Abc', ('Def', 'GGGG'), 'JKL']
>>> autocorrect(['abC', 'gggg', 'jkL'])
['Abc', 'GGGG', 'jkL']
"Abc"
总是被放入相同的形式中,并且"Def"
在"GGGG"
使用时也是如此。然而,不同的形式"Jkl"
永远不会被修改,因为它们每个都遵循不同的早期值。
如果您的数据库无法更改,这可能是最好的解决方案,但更简单的方法是简单地强制所有数据进入相同的规范化方案。您可能可以编写一些相当简单的代码来检查现有数据以使其保持一致,然后只需标准化您获得的每个新项目,而无需担心以前的条目是什么。