网上的方法有不少,都是一样的原理,按照需求,做了一下版本的class类文件,主要功能是:功能明确,易于修改维护和扩展; 英文的字串:不变返回(包括数字);中文字符串:返回拼音首字符; 中英混合串: 返回拼音首字符和英文。该算法采用了二分法查找,修复了之前字母Z读取成Y的错误。好东西要收藏,故在此留下印记,以供后人考证!
<?php <BR> /**<BR>* Modified by http://iulog.com @ 2013-05-07<BR>* 修复二分法查找方法<BR>* 汉字拼音首字母工具类<BR>* 注: 英文的字串:不变返回(包括数字) eg .abc123 => abc123<BR>* 中文字符串:返回拼音首字符 eg. 测试字符串 => CSZFC<BR>* 中英混合串: 返回拼音首字符和英文 eg. 我i我j => WIWJ<BR>* eg.<BR>* $py = new str2PY();<BR>* $result = $py->getInitials('啊吧才的饿飞就好i就看了吗你哦平去人是他uv我想一在');<BR>*/<BR>class str2PY<BR>{<BR> private $_pinyins = array(<BR> 176161 => 'A',<BR> 176197 => 'B',<BR> 178193 => 'C',<BR> 180238 => 'D',<BR> 182234 => 'E',<BR> 183162 => 'F',<BR> 184193 => 'G',<BR> 185254 => 'H',<BR> 187247 => 'J',<BR> 191166 => 'K',<BR> 192172 => 'L',<BR> 194232 => 'M',<BR> 196195 => 'N',<BR> 197182 => 'O',<BR> 197190 => 'P',<BR> 198218 => 'Q',<BR> 200187 => 'R',<BR> 200246 => 'S'<i>·本2文来源gaodai$ma#com搞$代*码网2</i><strong>搞gaodaima代码</strong>,<BR> 203250 => 'T',<BR> 205218 => 'W',<BR> 206244 => 'X',<BR> 209185 => 'Y',<BR> 212209 => 'Z',<BR> );<BR> private $_charset = null;<BR> /**<BR> * 构造函数, 指定需要的编码 default: utf-8<BR> * 支持utf-8, gb2312<BR> *<BR> * @param unknown_type $charset<BR> */<BR> public function __construct( $charset = 'utf-8' )<BR> {<BR> $this->_charset = $charset;<BR> }<BR> /**<BR> * 中文字符串 substr<BR> *<BR> * @param string $str<BR> * @param int $start<BR> * @param int $len<BR> * @return string<BR> */<BR> private function _msubstr ($str, $start, $len)<BR> {<BR> $start = $start * 2;<BR> $len = $len * 2;<BR> $strlen = strlen($str);<BR> $result = '';<BR> for ( $i = 0; $i < $strlen; $i++ ) {<BR> if ( $i >= $start && $i < ($start + $len) ) {<BR> if ( ord(substr($str, $i, 1)) > 129 ) $result .= substr($str, $i, 2);<BR> else $result .= substr($str, $i, 1);<BR> }<BR> if ( ord(substr($str, $i, 1)) > 129 ) $i++;<BR> }<BR> return $result;<BR> }<BR> /**<BR> * 字符串切分为数组 (汉字或者一个字符为单位)<BR> *<BR> * @param string $str<BR> * @return array<BR> */<BR> private function _cutWord( $str )<BR> {<BR> $words = array();<BR> while ( $str != "" )<BR> {<BR> if ( $this->_isAscii($str) ) {/*非中文*/<BR> $words[] = $str[0];<BR> $str = substr( $str, strlen($str[0]) );<BR> }else{<BR> $word = $this->_msubstr( $str, 0, 1 );<BR> $words[] = $word;<BR> $str = substr( $str, strlen($word) );<BR> }<BR> }<BR> return $words;<BR> }<BR> /**<BR> * 判断字符是否是ascii字符<BR> *<BR> * @param string $char<BR> * @return bool<BR> */<BR> private function _isAscii( $char )<BR> {<BR> return ( ord( substr($char,0,1) ) < 160 );<BR> }<BR> /**<BR> * 判断字符串前3个字符是否是ascii字符<BR> *<BR> * @param string $str<BR> * @return bool<BR> */<BR> private function _isAsciis( $str )<BR> {<BR> $len = strlen($str) >= 3 ? 3: 2;<BR> $chars = array();<BR> for( $i = 1; $i < $len -1; $i++ ){<BR> $chars[] = $this->_isAscii( $str[$i] ) ? 'yes':'no';<BR> }<BR> $result = array_count_values( $chars );<BR> if ( empty($result['no']) ){<BR> return true;<BR> }<BR> return false;<BR> }<BR> /**<BR> * 获取中文字串的拼音首字符<BR> *<BR> * @param string $str<BR> * @return string<BR> */<BR> public function getInitials( $str )<BR> {<BR> if ( empty($str) ) return '';<BR> if ( $this->_isAscii($str[0]) && $this->_isAsciis( $str )){<BR> return $str;<BR> }<BR> $result = array();<BR> if ( $this->_charset == 'utf-8' ){<BR> $str = iconv( 'utf-8', 'gb2312', $str );<BR> }<BR> $words = $this->_cutWord( $str );<BR> foreach ( $words as $word )<BR> {<BR> if ( $this->_isAscii($word) ) {/*非中文*/<BR> $result[] = $word;<BR> continue;<BR> }<BR> $code = ord( substr($word,0,1) ) * 1000 + ord( substr($word,1,1) );<BR> /*获取拼音首字母A--Z*/<BR> if ( ($i = $this->_search($code)) != -1 ){<BR> $result[] = $this->_pinyins[$i];<BR> }<BR> }<BR> return strtoupper(implode('',$result));<BR> }<BR> private function _getChar( $ascii )<BR> {<BR> if ( $ascii >= 48 && $ascii <= 57){<BR> return chr($ascii); /*数字*/<BR> }elseif ( $ascii>=65 && $ascii<=90 ){<BR> return chr($ascii); /* A--Z*/<BR> }elseif ($ascii>=97 && $ascii<=122){<BR> return chr($ascii-32); /* a--z*/<BR> }else{<BR> return '-'; /*其他*/<BR> }<BR> }</P><P> /**<BR> * 查找需要的汉字内码(gb2312) 对应的拼音字符( 二分法 )<BR> *<BR> * @param int $code<BR> * @return int<BR> */<BR> private function _search( $code )<BR> {<BR> $data = array_keys($this->_pinyins);<BR> $lower = 0;<BR> $upper = sizeof($data)-1;<BR> $middle = (int) round(($lower + $upper) / 2);<BR> if ( $code < $data[0] ) return -1;<BR> for (;;) {<BR> if ( $lower > $upper ){<BR> return $data[$lower-1];<BR> }<BR> $tmp = (int) round(($lower + $upper) / 2);<BR> if ( !isset($data[$tmp]) ){<BR> return $data[$middle];<BR> }else{ <BR> $middle = $tmp;<BR> }<BR> if ( $data[$middle] < $code ){<BR> $lower = (int)$middle + 1;<BR> }else if ( $data[$middle] == $code ) {<BR> return $data[$middle];<BR> }else{<BR> $upper = (int)$middle - 1;<BR> }<BR> }<BR> }<BR>}<BR>?><BR>