Answers
看到你的问题,我以前在一个社区里变见过一个答案,感觉挺好,你参考下,当然是PHP语言方面,不过大致原理就这样:
1.拼音库
首先需要一个拼音库,里面记录着所有常用汉字的拼音
例如:
'中' => 'zhong'
'张' => 'zhang'
'网' => 'wang'
2.建立索引
这里以用户的手机通讯录为例,现在几乎每个人都有一个或多个手机,手机里面多少会有一些联系人。假设现在要实现这样一个需求,可以通过姓名或电话进行联系人搜索,这样我们将姓名及电话里面的值进行索引即可,索引的时候采用增量索引,也就是那条数据修改了,就更新对应数据的索引,没有发生变化的数据不建立索引,节省时间。
增量索引时,怎样判断数据是否已经改变了呢?首先数据库里面有一份数据,索引里面有一份数据,我们要对姓名及电话进行索引,对比一下姓名及电话的值,如果完全相同,则不需要再次建立索引了,原理很简单。
同一次建立索引的时候可以把汉字转换拼音的结果缓存到内存中,索引建立完成以后内存中的数据自动消失,因为拼音库是一个关联数组,里面的数据很多,查找起来比较花时间。
比如有以下的姓名:
张三
李四
张东
张西
李涛
张南
里面有4个姓张的,两个姓李的,这样汉字转拼音的时候张字及李字只用转换一次即可,下次直接从内存里面取数据,性能上可以得到一些提升,相同的汉字越多,则性能提高得越多。
/**
* 如果$s为北京,则函数str2py的返回值为beijing, $firstPy的结果为bj
*/
function str2py($s, &$firstPy = '', $charset = 'UTF-8') {
if (empty($s)) return '';
global $py_dic;
if (!is_array($py_dic)) {
include_once(dirname(__FILE__) . '/py_dic.php');
}
$s = strtolower($s);
$len = mb_strlen($s, $charset);
for ($i = 0; $i < $len; $i++) {
$key = mb_substr($s, $i, 1, $charset);
if (ord($key) > 128) {
//如果缓存里面有数据,直接从缓存里面取数据
$char = isset($GLOBALS["py_$key"]) ? $GLOBALS["py_$key"] : $py_dic[$key];
if ($char) {
$firstPy .= substr($char, 0, 1);
//将拼音转换的结果缓存起来,让后面的使用
!isset($GLOBALS["py_$key"]) && $GLOBALS["py_$key"] = $char;
}
$py .= $char;
} else {
$py .= $key;
}
}
return $py;
}
联系人的元数据一般是保存在数据库中,比如MySQL,索引的数据可以保存在文件中,也可以保存在NoSQL中,比如TT,每个用户一个key, 值是二维数据的值json_encode以后保存到TT中。
3.搜索
比如某个联系人的姓名为“张三”,则建立的索引值为\u5f20\u4e91|zhangsan|zs,包括张三这两个汉字本身 加上 张三的全拼 加上 拼音的首字母,这样用户输入张三、zhangsan、zs等均可搜索出张三,当然也支持模糊匹配,比如输入张、zhang、zhangs、z、han、ang、gsa也可以搜索出张三。
4.拼音搜索应用
a.58同城的列车时刻表查询,http://lieche.58.com/
b.去哪儿首页的国内机票查询,http://www.qunar.com/
c.搜房网的房子查询,http://www.soufun.com/
延伸阅读:
http://www.baidu.com/s?wd=php+%BA%BA%D7%D6%D7%AA%C6%B4%D2%F4
ACG初心者
answered 12 years, 1 month ago