在開發通訊錄、城市選擇器或索引列表時,常需要將中文轉換為拼音首字母以便排序或分組。這篇文章提供一個基於 GB2312 編碼區間對照表的 PHP 實作方案。
GB2312 編碼中,漢字佔用兩個位元組,其區位碼對應特定範圍。透過建立「首字母-區位碼區間」對照表,即可將漢字映射為 A-Z 大寫字母。
<?php
$limit = array(
// GB2312 拼音排序區間
array(45217, 45252), // A
array(45253, 45760), // B
array(45761, 46317), // C
array(46318, 46825), // D
array(46826, 47009), // E
array(47010, 47296), // F
array(47297, 47613), // G
array(47614, 48118), // H
array(0, 0), // I (無對應漢字)
array(48119, 49061), // J
array(49062, 49323), // K
array(49324, 49895), // L
array(49896, 50370), // M
array(50371, 50613), // N
array(50614, 50621), // O
array(50622, 50905), // P
array(50906, 51386), // Q
array(51387, 51445), // R
array(51446, 52217), // S
array(52218, 52697), // T
array(0, 0), // U
array(0, 0), // V
array(52698, 52979), // W
array(52980, 53688), // X
array(53689, 54480), // Y
array(54481, 55289) // Z
);
$str = "A:這是一個測試程序1";
// 轉為 GB2312 以利區位碼計算
$str = iconv("UTF-8", "gb2312", $str);
echo $str . "<br>";
$i = 0;
while ($i < strlen($str)) {
$tmp = bin2hex(substr($str, $i, 1));
if ($tmp >= 'B0') { // 漢字起始位元組
// 取兩個位元組轉為十進位區位碼
$code = hexdec(bin2hex(substr($str, $i, 2)));
$letter = getLetter($code);
printf("%c", $letter == -1 ? '*' : $letter);
$i += 2;
} else {
// 英數字元直接輸出
printf("%s", substr($str, $i, 1));
$i++;
}
}
function getLetter($num) {
global $limit;
$char_index = 65; // ASCII 'A'
foreach ($limit as $k => $v) {
if ($num >= $v[0] && $num <= $v[1]) {
$char_index += $k;
return $char_index;
}
}
return -1;
}
?>
輸出:A:ZSYYGCSXC1(對應「這是一個測試程序」的首字母)
pinyin 等成熟 Composer 套件,支援 UTF-8 且維護性更佳