browser icon
You are using an insecure version of your web browser. Please update your browser!
Using an outdated browser makes your computer unsafe. For a safer, faster, more enjoyable user experience, please update your browser today or try a newer browser.

伤不起的多音字

Posted by on 2011 年 09 月 27 日

你可以任意转载本文,但请在转载后的文章中注明作者和原始链接。
媒体约稿请联系 titilima_AT_163.com(把“_AT_”换成“@”)。

先从一段代码开始吧。这段代码来自于某个版本的灵图天行者,由于年代久远,所以我并不能保证它完全一致。不过,代码的用意和精髓我还是能够保证忠实还原的。

1
2
3
4
5
6
7
8
9
10
int __cdecl foo(const void* p1, const void* p2)
{
    PCWSTR pwz1 = (PCWSTR)p1;
    PCWSTR pwz2 = (PCWSTR)p2;
    if (0 == wcscmp(pwz1, L"重庆"))
        pwz1 = L"冲庆";
    if (0 == wcscmp(pwz2, L"重庆"))
        pwz2 = L"冲庆";
    return wcscmp(pwz1, pwz2);
}

简单解释一下,这是一个回调函数,被传递给 CRT 的 qsort 函数,用于对省级行政区进行名称排序。代码的用意也很简单,当传入的字符串参数是“重庆”时,以“冲庆”代替之进行比较。
因为“重庆”的“重”是多音字。在普通的字符串之中,被按“zhong”处理了,如果直接排序的话,最后得到的结果将是错误的。考虑如下代码:

int x = wcscmp(L"重庆", L"河北"); // wcscmp returns 1

在我看来,虽然 foo 这个函数可以完成正确的排序,但未免不够优雅。但似乎又没有什么更好的解决方案,于是 foo 的做法保留了很长时间——2009 年后也许有了更好的处理方法,不过我不知道。而且由于我后来离开了 GIS 这个行业,所以逐渐淡忘了这个事情。

不过,一个偶然的机会,iOS 的通讯录给了我一个更好的答案。

如上图所示,一名曾姓童鞋被归入了 C 的索引,有如重庆之于 zhong 庆。不过,通讯录却为用户提供了一个解决方案:

简单来说,为记录增加了一个排序参考字段。如果该字段非空,则以该字段为排序标准,否则以名称为排序标准。问题得以解决。

订阅本站

3 Comments

  • At 2011.09.28 02:28, 勾三股四 said:

    好想法!生僻字在比较的时候都会被比到最后面,应该也可以用类似的方法解决。
    不过更智能的当然是通过分词和上下文语境做判断了,这个就不好搞了

    • At 2011.10.09 23:48, 匿名 said:

      李马不会是学G I S的吧?

      • At 2011.10.10 13:19, 李马 said:

        第一份工作是这方面。

        (Required)
        (Required, will not be published)