php获取汉字首字母的函数

本文介绍用php实现汉字转化为首字母的方法,主要功能是:功能明确,易于修改维护和扩展; 英文的字串:不变返回(包括数字);中文字符串:返回拼音首字符; 中英混合串: 返回拼音首字符和英文

网上的方法有不少,都是一样的原理,按照需求,做了一下版本的class类文件,主要功能是:功能明确,易于修改维护和扩展; 英文的字串:不变返回(包括数字);中文字符串:返回拼音首字符; 中英混合串: 返回拼音首字符和英文。该算法采用了二分法查找,修复了之前字母Z读取成Y的错误。好东西要收藏,故在此留下印记,以供后人考证!

  1. <?php
  2. /**
  3. * Modified by http://iulog.com @ 2013-05-07
  4. * 修复二分法查找方法
  5. * 汉字拼音首字母工具类
  6. * 注: 英文的字串:不变返回(包括数字) eg .abc123 => abc123
  7. * 中文字符串:返回拼音首字符 eg. 测试字符串 => CSZFC
  8. * 中英混合串: 返回拼音首字符和英文 eg. 我i我j => WIWJ
  9. * eg.
  10. * $py = new str2PY();
  11. * $result = $py->getInitials('啊吧才的饿飞就好i就看了吗你哦平去人是他uv我想一在');
  12. */
  13. class str2PY
  14. {
  15. private $_pinyins = array(
  16. 176161 => 'A',
  17. 176197 => 'B',
  18. 178193 => 'C',
  19. 180238 => 'D',
  20. 182234 => 'E',
  21. 183162 => 'F',
  22. 184193 => 'G',
  23. 185254 => 'H',
  24. 187247 => 'J',
  25. 191166 => 'K',
  26. 192172 => 'L',
  27. 194232 => 'M',
  28. 196195 => 'N',
  29. 197182 => 'O',
  30. 197190 => 'P',
  31. 198218 => 'Q',
  32. 200187 => 'R',
  33. 200246 => 'S',
  34. 203250 => 'T',
  35. 205218 => 'W',
  36. 206244 => 'X',
  37. 209185 => 'Y',
  38. 212209 => 'Z',
  39. );
  40. private $_charset = null;
  41. /**
  42. * 构造函数, 指定需要的编码 default: utf-8
  43. * 支持utf-8, gb2312
  44. *
  45. * @param unknown_type $charset
  46. */
  47. public function __construct( $charset = 'utf-8' )
  48. {
  49. $this->_charset = $charset;
  50. }
  51. /**
  52. * 中文字符串 substr
  53. *
  54. * @param string $str
  55. * @param int $start
  56. * @param int $len
  57. * @return string
  58. */
  59. private function _msubstr ($str, $start, $len)
  60. {
  61. $start = $start * 2;
  62. $len = $len * 2;
  63. $strlen = strlen($str);
  64. $result = '';
  65. for ( $i = 0; $i < $strlen; $i++ ) {
  66. if ( $i >= $start && $i < ($start + $len) ) {
  67. if ( ord(substr($str, $i, 1)) > 129 ) $result .= substr($str, $i, 2);
  68. else $result .= substr($str, $i, 1);
  69. }
  70. if ( ord(substr($str, $i, 1)) > 129 ) $i++;
  71. }
  72. return $result;
  73. }
  74. /**
  75. * 字符串切分为数组 (汉字或者一个字符为单位)
  76. *
  77. * @param string $str
  78. * @return array
  79. */
  80. private function _cutWord( $str )
  81. {
  82. $words = array();
  83. while ( $str != "" )
  84. {
  85. if ( $this->_isAscii($str) ) {/*非中文*/
  86. $words[] = $str[0];
  87. $str = substr( $str, strlen($str[0]) );
  88. }else{
  89. $word = $this->_msubstr( $str, 0, 1 );
  90. $words[] = $word;
  91. $str = substr( $str, strlen($word) );
  92. }
  93. }
  94. return $words;
  95. }
  96. /**
  97. * 判断字符是否是ascii字符
  98. *
  99. * @param string $char
  100. * @return bool
  101. */
  102. private function _isAscii( $char )
  103. {
  104. return ( ord( substr($char,0,1) ) < 160 );
  105. }
  106. /**
  107. * 判断字符串前3个字符是否是ascii字符
  108. *
  109. * @param string $str
  110. * @return bool
  111. */
  112. private function _isAsciis( $str )
  113. {
  114. $len = strlen($str) >= 3 ? 3: 2;
  115. $chars = array();
  116. for( $i = 1; $i < $len -1; $i++ ){
  117. $chars[] = $this->_isAscii( $str[$i] ) ? 'yes':'no';
  118. }
  119. $result = array_count_values( $chars );
  120. if ( emptyempty($result['no']) ){
  121. return true;
  122. }
  123. return false;
  124. }
  125. /**
  126. * 获取中文字串的拼音首字符
  127. *
  128. * @param string $str
  129. * @return string
  130. */
  131. public function getInitials( $str )
  132. {
  133. if ( emptyempty($str) ) return '';
  134. if ( $this->_isAscii($str[0]) && $this->_isAsciis( $str )){
  135. return $str;
  136. }
  137. $result = array();
  138. if ( $this->_charset == 'utf-8' ){
  139. $str = iconv( 'utf-8', 'gb2312', $str );
  140. }
  141. $words = $this->_cutWord( $str );
  142. foreach ( $words as $word )
  143. {
  144. if ( $this->_isAscii($word) ) {/*非中文*/
  145. $result[] = $word;
  146. continue;
  147. }
  148. $code = ord( substr($word,0,1) ) * 1000 + ord( substr($word,1,1) );
  149. /*获取拼音首字母A--Z*/
  150. if ( ($i = $this->_search($code)) != -1 ){
  151. $result[] = $this->_pinyins[$i];
  152. }
  153. }
  154. return strtoupper(implode('',$result));
  155. }
  156. private function _getChar( $ascii )
  157. {
  158. if ( $ascii >= 48 && $ascii <= 57){
  159. return chr($ascii); /*数字*/
  160. }elseif ( $ascii>=65 && $ascii<=90 ){
  161. return chr($ascii); /* A--Z*/
  162. }elseif ($ascii>=97 && $ascii<=122){
  163. return chr($ascii-32); /* a--z*/
  164. }else{
  165. return '-'; /*其他*/
  166. }
  167. }
  168. /**
  169. * 查找需要的汉字内码(gb2312) 对应的拼音字符( 二分法 )
  170. *
  171. * @param int $code
  172. * @return int
  173. */
  174. private function _search( $code )
  175. {
  176. $data = array_keys($this->_pinyins);
  177. $lower = 0;
  178. $upper = sizeof($data)-1;
  179. $middle = (int) round(($lower + $upper) / 2);
  180. if ( $code < $data[0] ) return -1;
  181. for (;;) {
  182. if ( $lower > $upper ){
  183. return $data[$lower-1];
  184. }
  185. $tmp = (int) round(($lower + $upper) / 2);
  186. if ( !isset($data[$tmp]) ){
  187. return $data[$middle];
  188. }else{
  189. $middle = $tmp;
  190. }
  191. if ( $data[$middle] < $code ){
  192. $lower = (int)$middle + 1;
  193. }else if ( $data[$middle] == $code ) {
  194. return $data[$middle];
  195. }else{
  196. $upper = (int)$middle - 1;
  197. }//phpfensi.com
  198. }
  199. }
  200. }
  201. ?>