把脏地址解析成区划码(二):那些不报错的错答案

4 阅读4分钟

上一篇讲了前 5 关,泛称被同音误伤、真歧义被当成错字、两字县名的子串、合称拆不开、单字别名越界。它们的共同点是全都不报错,只是给出一个看着像的错答案。

这一篇还是这个主题,只不过错得更安静。5 关里有 3 关来自 295 条那一轮,2 关来自扩到 1,168 条之后。

第 6 关:海南藏族自治州 变成了海南省

青海的海南藏族自治州,被解析成了海南省。

因为省级匹配走的是去后缀短形式"海南",而这个位置其实是一个更长地名的开头。同一批还有个 海南区,内蒙古乌海的,现在能正确落在乌海市。

改法:短形式命中时,检查该位置有没有更长的已知区划名,有就不作数。

第 7 关:南京市 变成了北京市

这关不报错,也不给候选,就是悄悄答错。前面几关好歹还能从"答案荒唐"里看出破绽,这一关的输出非常正常,所以单独写一下。

南京市北京市 逐字比对只差一个字,南和北。我那套"模糊匹配(编辑距离 1)"把前者当成了后者的错字,降了一点置信度就返回北京市。

改法是给模糊匹配加两道闸。命中的那段如果本身就是现行区划名,跳过;拼音对不上(nan-jing-shi 不等于 bei-jing-shi),也跳过。字距 1 但读音完全不同,多半就是另一个词。

第 8 关:西鞍 落到了"西安区×2"

西鞍 是西安的同音错字,纠错方向是对的。但西安的同音候选里既有西安市,也有两个"西安区"。原来的取法是"取第一个能解析的",于是随机落到了低层级而且不相关的候选上。

改法:候选要择优。优先返回唯一解析,也就是西安市;所有候选都只能得到歧义时,才退回去给候选集。

第 9 关:名字对了,码是空的

题量扩到 1,168 条之后,这一关冒出来了。

输入修之前问题
浙江省西湖区浙江省-西湖区串看着对,但 county 码是 null
河北省桥西区["河北省-桥西区", "河北省-桥西区"]候选重复两次,而且都丢了市级

第一行尤其麻烦。输出长得没毛病,码却没了。对一个卖码的工具来说,名字对、码没有,等于没交付。

根因是,当输入里只有省、没有市的时候,引擎在全省范围找到县名之后,没有反查这个县到底属于哪个地级市,市级字段和县级码就一起丢了。

改法:反查所属地级再补全。单命中补全,多命中按(市,县)去重展开成候选。

第 10 关:喀什地区 变成了喀什市

同一批里还有一串同类问题。和田地区变成了和田市 / 和田县的候选集,喀什地区变成了喀什市,红河哈尼族彝族自治州变成了红河县,跟州名只是前缀相同。

根因是,全库县级直配比地级匹配先跑,于是"喀什"这两个字先命中了它下辖的县级市。

改法:省未命中时,先做地级全名直配,要求整串相等,然后再走县级直配。整串相等这个限制保住了 杭州市西湖区 这类带下级的输入。


这两批的账

本篇这 5 关每条都补了 3 条以上回归,共 20 条
累计修掉的解析缺陷10 个
累计新增回归用例41 条,回归集从 110 条扩到 151 条,全绿
评测集规模128 → 295 → 1,168 条
自动生成的历史别名888 条
旧码到现行码的映射1,928 条

引擎和数据在 GitHub:github.com/nbsetsail/r… 。代码 MIT,数据 CC-BY-4.0,署名即可使用。脏地址解析可离线跑,有 CLI。

下一篇讲后面 5 关,涉及层级、时间机器,以及一处根因不在引擎、而在数据本身的问题。