如何自定义python-levenshtein字符值以适配爱尔兰语文本正字法变化
解决python-levenshtein对爱尔兰语正字法变体的相似度计算问题
我明白你的需求——你在用python-levenshtein分析跨时间维度的爱尔兰语文本,这些文本里的正字法变体(比如bí→ḃí→bhí)其实是同一语法弱化形式,但默认的Levenshtein.ratio把它们当成完全不同的字符处理,导致相似度偏低。下面给你两个实用的解决方案,优先推荐第一种,简单直接还精准。
方案一:正字法归一化(最推荐)
核心思路是先把所有等价的正字法变体转换成统一的基础形式,再计算Levenshtein距离。这样语义/语法等价的文本归一化后完全一致,相似度自然拉满。
步骤1:构建爱尔兰语正字法映射表
把表示相同语法功能的变体映射到同一个基础字符,比如把弱化形式的ḃ、bh都映射回原始的b:
# 可根据爱尔兰语正字法规则,补充更多变体 ortho_map = { # 辅音弱化的变体映射 'ḃ': 'b', 'bh': 'b', 'ḋ': 'd', 'dh': 'd', 'ḟ': 'f', 'fh': 'f', 'ġ': 'g', 'gh': 'g', 'ṁ': 'm', 'mh': 'm', 'ṗ': 'p', 'ph': 'p', 'ṡ': 's', 'sh': 's', 'ṫ': 't', 'th': 't', }
注意:要优先处理多字符变体(比如bh),避免单字符变体先替换导致匹配错误,后续处理时要按字符长度从长到短排序。
步骤2:编写归一化函数
这个函数会把输入文本里的所有变体替换成统一形式:
def normalize_irish_text(text): # 按变体的字符长度从长到短排序,确保多字符变体先被替换 sorted_variants = sorted(ortho_map.keys(), key=lambda x: len(x), reverse=True) normalized_text = text for variant in sorted_variants: normalized_text = normalized_text.replace(variant, ortho_map[variant]) return normalized_text
步骤3:结合python-levenshtein计算相似度
现在用归一化后的文本计算,就能得到符合预期的结果:
from Levenshtein import ratio # 测试正字法变体 text_original = "bí" text_lenited_1 = "ḃí" text_lenited_2 = "bhí" # 归一化处理 norm_original = normalize_irish_text(text_original) norm_lenited_1 = normalize_irish_text(text_lenited_1) norm_lenited_2 = normalize_irish_text(text_lenited_2) # 计算相似度 print(f"原始bí和ḃí的相似度:{ratio(norm_original, norm_lenited_1)}") # 输出1.0 print(f"原始bí和bhí的相似度:{ratio(norm_original, norm_lenited_2)}") # 输出1.0 print(f"ḃí和bhí的相似度:{ratio(norm_lenited_1, norm_lenited_2)}") # 输出1.0
对于更长的文本,这个方法同样适用,能有效消除正字法变化带来的不必要距离。
方案二:自定义编辑成本(保留细微差异时用)
如果你不想完全归一化,而是希望给这些变体设置更低的替换成本(比如让ḃ替换成b的成本远低于普通字符替换),可以手动处理编辑操作的权重:
from Levenshtein import editops def custom_irish_ratio(text_a, text_b): total_cost = 0 max_length = max(len(text_a), len(text_b)) # 获取所有编辑操作 operations = editops(text_a, text_b) for op_type, idx_a, idx_b in operations: if op_type == 'replace': char_a = text_a[idx_a] char_b = text_b[idx_b] # 检查两个字符是否是等价的正字法变体 mapped_a = ortho_map.get(char_a, char_a) mapped_b = ortho_map.get(char_b, char_b) if mapped_a == mapped_b: # 等价变体,设置低替换成本 total_cost += 0.1 else: # 普通替换,成本为1 total_cost += 1 else: # 插入或删除操作,成本为1 total_cost += 1 # 计算自定义相似度(1 - 总成本/最大长度) return 1 - (total_cost / max_length) # 测试单字符变体 print(f"自定义相似度:bí vs ḃí = {custom_irish_ratio('bí', 'ḃí')}") # 输出约0.95
⚠️ 注意:这个方法对多字符变体(比如bh)处理起来比较麻烦,因为editops会把bí和bhí识别为插入一个h的操作,而非替换b为bh,所以如果你的文本里有大量多字符正字法变体,优先用方案一。
内容的提问来源于stack exchange,提问作者Charlie Tizzard Ó Kevlahan
相关产品推荐
相关产品推荐

