最近项目上有个需求,需要将一些联系人数据按照拼音首字母排序。google 了一番,竟然没有找到一个合适的 Lua 解决方案。倒是找到一个 lua-pinyin,粗略翻了下源码发现其是将所有的中文返回全部完整的拼音,原理是将所有汉字对应拼音创建好数据字典,载入 Lua,之后查询这个字典,返回对应的拼音。但是这对于我这个需求来说显然是太臃肿了,我只需要返回首字母就可以了,却载入一个巨大的字典,感觉有点浪费内存,尤其是在 OR 对于 Lua 的内存是有限制的情况下。
为此自己造了个轮子:lua-resty-pyf,感兴趣的同学可以去 github 搜下。这里我来说下原理。
如果单从排序的角度来看,我们其实完全可以利用 GBK 中文的顺序编码来解决,而且 GBK 是固定字节编码,即:两个字节(一个区码和一个位码)。我们先计算出汉字对应的 GBK 码点,之后按照码点排序就实现了首字母的排序。
如果需要提取出首字母用于检索,我们就必须建立一个映射关系,把所有汉字对应的首字母全部映射进去。好在已经有个老外做了这部分的工作,这里我用 ffi 简单封装了下,暴露出了 lua 的接口。
需要注意的是我们这里使用的是 Unicode 的码点。也许你现在有个疑问?不是说 Lua 5.1 以下都是不支持 Unicode 的吗?
首先 lua string 是一个 raw buffer,按字节存储的,是 \0(null)
安全的,可以存放任意数据。也就是说你可以在里面存放任何数据,不管是 UTF-8 还是 GBK,最后你只需要用正确的编码显示出来就可以得到正确的结果。我们想要的所谓支持 unicode 的 lua,到底是什么意思呢?最基础的大概就是能像 string.sub
string.len
可以得到正确的 Unicode 结果的能力,即 locale 化。lua 原生是不提供任何正常化 Unicode 字符串的能力。但是借助 luajit 的 bit 我们可以自己实现这样的功能。
正如 lua FAQ 中的问题:我可以使用 Unicode 字符串么?或者,Lua 支持 Unicode 么?
简而言之,可以,不支持。