这是一个非常经典的问题,同时,也是一个很难解决的问题。经典是因为,这个问题非常常见,而且有很多解决方案。

难以解决是因为,存在多音字。可以发现很多股票软件都有这问题,比如zgyh 出来的不是中国银行,而是找不到,

这是因为,中国银行的 “行” 查出来读的是 "xing" 。我篇文章我只是提供了一个原始的转换方法,就是查表。

和你以前看过的算法可能不一样的是,我加了一个二分查找,我看到的一个开源的解决方案是顺序查找的。

    关于,多音字问题,我只有一个小规模的多音字表,从所有股票名称里面纠正过来的。解决方案是这样的:在查找拼音的时候,

查找一下这个字是否在多音字表里面,如果是,那么查找前后组成的词,来决定读什么。如果有谁有完整的多音字表,或者有更好的

解决方案,请给我留言。我一定拜谢。

代码
<?php
/**
 * 初始化
 *
 * @param string $file 拼音代码对应表
 * @return array 把这个对应表映射成array的格式
 
*/
function pinyin_init($file)
{
    
$pinyin = file($file);
    
if (empty($pinyin)) {
        
throw new Exception("load pinyin table error.");
    }
    
foreach ($pinyin as $k => $item)
    {
        
$item = explode("\t", $item);
        
$item[0= trim($item[0]);
        
$item[1= (int)trim($item[1]);
        
$pinyin[$k= $item;
    }
    
$pinyin[] = array('', -10248); //最后一个拼音的妈是 -10247
    return $pinyin;
}

/**
 * 查找一个字符串中,中文字符部分的拼音
 *
 * @param array $pingyin
 * @param string $str       字符串
 * @param string $in_encode 字符串的编码
 * @return array
 
*/
function pingyin_get($pingyin, $str, $in_encode = 'gb2312')
{
    
if (strtolower($in_encode!= 'gb2312') {
       
$str = iconv($in_encode, 'gb2312', $str);
       
if (!$str) {
           
throw new Exception('invalid input string.');
       }
    }
    
$pinyin_arr = array();
    
$len = strlen($str);
    
for ($i = 0$i < $len$i++)
    {
        
if ($i == $len -1break;
        
if (($code = pinyin_getcode_($str[$i], $str[$i + 1])) != false) {
            
$i++;
            
if (($py = pinyin_find_($pingyin, $code)) !== false) {
                
$pinyin_arr[substr($str, $i - 1 , 2)] = $py;
            }
        }
    }
    
return $pinyin_arr;
}

/**
 * 内部函数,通过拼音码查找汉字
 *
 * @param array $pingyin
 * @param int $code
 * @return string/false 
 
*/
function pinyin_find_($pingyin, $code)
{
    
$start = 0;
    
$count = count($pingyin- 1;
    
$end = $count;
    
if ($code < $pingyin[0][1|| $code >= $pingyin[$end][1]) { //no found.
        return false;
    }
    
while ($start <= $end)
    {
        
$mid = (int)($start + ($end - $start)/2);
        
if ($mid == $count) { //正常情况下,应该是永远都不会执行到这里,但是为了逻辑上清晰点,还是决定写上
            return $pingyin[$mid - 1][0];
        } 
else if ($code >= $pingyin[$mid][1&& $code < $pingyin[$mid + 1][1]) {
            
return $pingyin[$mid][0];
        } 
else if ($code >= $pingyin[$mid + 1][1]) {
           
$start = $mid + 1;
        } 
else {
            
$end = $mid - 1;
        }
    }
    
return false;
}

/**
 * 内部函数,通过汉字的第一个字节 和 第二个字节,得到查找的code
 *
 * @param char $ch1
 * @param char $ch2
 * @return int
 
*/
function pinyin_getcode_($ch1, $ch2)
{
    
$num1 = ord($ch1);
    
$num2 = ord($ch2);
    
if ($num1 > 159 && $num1 < 248) {
        
return $num1 * 256 + $num2 - 65536;
    }
    
return false;
}

/**
 * 基本配置信息
 
*/
define("CURRENT_PATH", dirname(__FILE__));
$pingin_file = CURRENT_PATH . "/gb-pinyin.table";

$pinyin = pinyin_init($pingin_file);
$py = pingyin_get($pinyin, "中国银行", 'utf-8');
echo iconv('gb2312', 'utf-8', print_r($py, true));
echo implode("'", $py);
?>

 <?php
/**
 * 初始化
 *
 * @param string $file 拼音代码对应表
 * @return array 把这个对应表映射成array的格式
 
*/
function pinyin_init($file)
{
    
$pinyin = file($file);
    
if (empty($pinyin)) {
        
throw new Exception("load pinyin table error.");
    }
    
foreach ($pinyin as $k => $item)
    {
        
$item = explode("\t", $item);
        
$item[0= trim($item[0]);
        
$item[1= (int)trim($item[1]);
        
$pinyin[$k= $item;
    }
    
$pinyin[] = array('', -10248); //最后一个拼音的妈是 -10247
    return $pinyin;
}

/**
 * 查找一个字符串中,中文字符部分的拼音
 *
 * @param array $pingyin
 * @param string $str       字符串
 * @param string $in_encode 字符串的编码
 * @return array
 
*/
function pingyin_get($pingyin, $str, $in_encode = 'gb2312')
{
    
if (strtolower($in_encode!= 'gb2312') {
       
$str = iconv($in_encode, 'gb2312', $str);
       
if (!$str) {
           
throw new Exception('invalid input string.');
       }
    }
    
$pinyin_arr = array();
    
$len = strlen($str);
    
for ($i = 0$i < $len$i++)
    {
        
if ($i == $len -1break;
        
if (($code = pinyin_getcode_($str[$i], $str[$i + 1])) != false) {
            
$i++;
            
if (($py = pinyin_find_($pingyin, $code)) !== false) {
                
$pinyin_arr[substr($str, $i - 1 , 2)] = $py;
            }
        }
    }
    
return $pinyin_arr;
}

/**
 * 内部函数,通过拼音码查找汉字
 *
 * @param array $pingyin
 * @param int $code
 * @return string/false 
 
*/
function pinyin_find_($pingyin, $code)
{
    
$start = 0;
    
$count = count($pingyin- 1;
    
$end = $count;
    
if ($code < $pingyin[0][1|| $code >= $pingyin[$end][1]) { //no found.
        return false;
    }
    
while ($start <= $end)
    {
        
$mid = (int)($start + ($end - $start)/2);
        
if ($mid == $count) { //正常情况下,应该是永远都不会执行到这里,但是为了逻辑上清晰点,还是决定写上
            return $pingyin[$mid - 1][0];
        } 
else if ($code >= $pingyin[$mid][1&& $code < $pingyin[$mid + 1][1]) {
            
return $pingyin[$mid][0];
        } 
else if ($code >= $pingyin[$mid + 1][1]) {
           
$start = $mid + 1;
        } 
else {
            
$end = $mid - 1;
        }
    }
    
return false;
}

/**
 * 内部函数,通过汉字的第一个字节 和 第二个字节,得到查找的code
 *
 * @param char $ch1
 * @param char $ch2
 * @return int
 
*/
function pinyin_getcode_($ch1, $ch2)
{
    
$num1 = ord($ch1);
    
$num2 = ord($ch2);
    
if ($num1 > 159 && $num1 < 248) {
        
return $num1 * 256 + $num2 - 65536;
    }
    
return false;
}

/**
 * 基本配置信息
 
*/
define("CURRENT_PATH", dirname(__FILE__));
$pingin_file = CURRENT_PATH . "/gb-pinyin.table";

$pinyin = pinyin_init($pingin_file);
$py = pingyin_get($pinyin, "中国银行", 'utf-8');
echo iconv('gb2312', 'utf-8', print_r($py, true));
echo implode("'", $py);
?>

拼音表如下:-20319
ai 
-20317
an 
-20304
ang 
-20295
ao 
-20292
ba 
-20283
bai 
-20265
ban 
-20257
bang 
-20242
bao 
-20230
bei 
-20051
ben 
-20036
beng 
-20032
bi 
-20026
bian 
-20002
biao 
-19990
bie 
-19986
bin 
-19982
bing 
-19976
bo 
-19805
bu 
-19784
ca 
-19775
cai 
-19774
can 
-19763
cang 
-19756
cao 
-19751
ce 
-19746
ceng 
-19741
cha 
-19739
chai 
-19728
chan 
-19725
chang 
-19715
chao 
-19540
che 
-19531
chen 
-19525
cheng 
-19515
chi 
-19500
chong 
-19484
chou 
-19479
chu 
-19467
chuai 
-19289
chuan 
-19288
chuang 
-19281
chui 
-19275
chun 
-19270
chuo 
-19263
ci 
-19261
cong 
-19249
cou 
-19243
cu 
-19242
cuan 
-19238
cui 
-19235
cun 
-19227
cuo 
-19224
da 
-19218
dai 
-19212
dan 
-19038
dang 
-19023
dao 
-19018
de 
-19006
deng 
-19003
di 
-18996
dian 
-18977
diao 
-18961
die -18952
ding 
-18783
diu 
-18774
dong 
-18773
dou 
-18763
du 
-18756
duan 
-18741
dui 
-18735
dun 
-18731
duo 
-18722
-18710
en 
-18697
er 
-18696
fa 
-18526
fan 
-18518
fang 
-18501
fei 
-18490
fen 
-18478
feng 
-18463
fo 
-18448
fou 
-18447
fu 
-18446
ga 
-18239
gai 
-18237
gan 
-18231
gang 
-18220
gao 
-18211
ge 
-18201
gei 
-18184
gen 
-18183
geng 
-18181
gong 
-18012
gou 
-17997
gu 
-17988
gua 
-17970
guai 
-17964
guan 
-17961
guang 
-17950
gui 
-17947
gun 
-17931
guo 
-17928
ha 
-17922
hai 
-17759
han 
-17752
hang 
-17733
hao 
-17730
he 
-17721
hei 
-17703
hen 
-17701
heng 
-17697
hong 
-17692
hou 
-17683
hu 
-17676
hua 
-17496
huai 
-17487
huan 
-17482
huang 
-17468
hui 
-17454
hun 
-17433
huo 
-17427
ji 
-17417
jia 
-17202
jian 
-17185
jiang 
-16983
jiao 
-16970
jie 
-16942
jin 
-16915
jing 
-16733
jiong 
-16708
jiu 
-16706
ju 
-16689
juan 
-16664
jue 
-16657
jun 
-16647
ka 
-16474
kai 
-16470
kan 
-16465
kang 
-16459
kao 
-16452
ke 
-16448
ken 
-16433
keng 
-16429
kong 
-16427
kou 
-16423
ku 
-16419
kua 
-16412
kuai 
-16407
kuan 
-16403
kuang 
-16401
kui 
-16393
kun 
-16220
kuo 
-16216
la 
-16212
lai 
-16205
lan 
-16202
lang 
-16187
lao 
-16180
le 
-16171
lei 
-16169
leng 
-16158
li 
-16155
lia 
-15959
lian 
-15958
liang 
-15944
liao 
-15933
lie 
-15920
lin 
-15915
ling 
-15903
liu 
-15889
long 
-15878
lou 
-15707
lu 
-15701
lv 
-15681
luan 
-15667
lue 
-15661
lun 
-15659
luo 
-15652
ma 
-15640
mai 
-15631
man 
-15625
mang 
-15454
mao 
-15448
me 
-15436
mei 
-15435
men 
-15419
meng 
-15416
mi 
-15408
mian 
-15394
miao 
-15385
mie 
-15377
min -15375
ming 
-15369
miu 
-15363
mo 
-15362
mou 
-15183
mu 
-15180
na 
-15165
nai 
-15158
nan 
-15153
nang 
-15150
nao 
-15149
ne 
-15144
nei 
-15143
nen 
-15141
neng 
-15140
ni 
-15139
nian 
-15128
niang 
-15121
niao 
-15119
nie 
-15117
nin 
-15110
ning 
-15109
niu 
-14941
nong 
-14937
nu 
-14933
nv 
-14930
nuan 
-14929
nue 
-14928
nuo 
-14926
-14922
ou 
-14921
pa 
-14914
pai 
-14908
pan 
-14902
pang 
-14894
pao 
-14889
pei 
-14882
pen 
-14873
peng 
-14871
pi -14857
pian 
-14678
piao 
-14674
pie 
-14670
pin 
-14668
ping 
-14663
po 
-14654
pu 
-14645
qi 
-14630
qia 
-14594
qian 
-14429
qiang 
-14407
qiao 
-14399
qie 
-14384
qin 
-14379
qing 
-14368
qiong 
-14355
qiu 
-14353
qu 
-14345
quan 
-14170
que 
-14159
qun 
-14151
ran 
-14149
rang 
-14145
rao 
-14140
re 
-14137
ren 
-14135
reng 
-14125
ri 
-14123
rong 
-14122
rou 
-14112
ru 
-14109
ruan 
-14099
rui 
-14097
run 
-14094
ruo 
-14092
sa 
-14090
sai 
-14087
san 
-14083
sang 
-13917
sao 
-13914
se 
-13910
sen 
-13907
seng 
-13906
sha 
-13905
shai 
-13896
shan 
-13894
shang 
-13878
shao 
-13870
she 
-13859
shen 
-13847
sheng 
-13831
shi 
-13658
shou 
-13611
shu 
-13601
shua 
-13406
shuai 
-13404
shuan 
-13400
shuang 
-13398
shui 
-13395
shun 
-13391
shuo 
-13387
si 
-13383
song 
-13367
sou 
-13359
su 
-13356
suan 
-13343
sui 
-13340
sun 
-13329
suo 
-13326
ta 
-13318
tai 
-13147
tan -13138
tang 
-13120
tao 
-13107
te 
-13096
teng 
-13095
ti 
-13091
tian 
-13076
tiao 
-13068
tie 
-13063
ting 
-13060
tong 
-12888
tou 
-12875
tu 
-12871
tuan 
-12860
tui 
-12858
tun 
-12852
tuo 
-12849
wa 
-12838
wai 
-12831
wan 
-12829
wang 
-12812
wei 
-12802
wen 
-12607
weng 
-12597
wo 
-12594
wu 
-12585
xi 
-12556
xia 
-12359
xian 
-12346
xiang 
-12320
xiao 
-12300
xie 
-12120
xin 
-12099
xing 
-12089
xiong 
-12074
xiu 
-12067
xu 
-12058
xuan 
-12039
xue 
-11867
xun 
-11861
ya 
-11847
yan 
-11831
yang 
-11798
yao 
-11781
ye 
-11604
yi 
-11589
yin 
-11536
ying 
-11358
yo 
-11340
yong 
-11339
you 
-11324
yu 
-11303
yuan 
-11097
yue 
-11077
yun 
-11067
za 
-11055
zai 
-11052
zan 
-11045
zang 
-11041
zao 
-11038
ze 
-11024
zei 
-11020
zen 
-11019
zeng 
-11018
zha 
-11014
zhai 
-10838
zhan 
-10832
zhang 
-10815
zhao 
-10800
zhe 
-10790
zhen 
-10780
zheng 
-10764
zhi 
-10587
zhong 
-10544
zhou 
-10533
zhu 
-10519
zhua 
-10331
zhuai 
-10329
zhuan 
-10328
zhuang 
-10322
zhui 
-10315
zhun 
-10309
zhuo 
-10307
zi 
-10296
zong 
-10281
zou 
-10274
zu 
-10270
zuan 
-10262
zui 
-10260
zun 
-10256
zuo 
-10254

posted on 2011-02-23 13:12  Right_MR  阅读(787)  评论(0编辑  收藏  举报