傳統中文檢索需輸入完整漢字,對不熟悉輸入法使用者門檻極高。利用漢字內碼 (Big5/GB) 與拼音首字母的固定對應關係,僅輸入拼音首字碼 (如「中國人民銀行」→「zgrmyh」) 即可快速檢索。本文完整實作首字碼對應表、檢索演算法、通配符支援與 Delphi 整合範例。
Big5 編碼中,漢字按拼音排序,同首字母漢字佔據連續內碼區間。以第一字節高位區分:
| 首字母 | 內碼範圍 (十六進位) | 說明 |
|---|---|---|
| A | $B0A1 - $B0C4 | |
| B | $B0C5 - $B2C0 | |
| C | $B2C1 - $B4ED | |
| D | $B4EE - $B6E9 | |
| E | $B6EA - $B7A1 | |
| F | $B7A2 - $B8C0 | |
| G | $B8C1 - $B9FD | |
| H | $B9FE - $BBF6 | |
| J | $BBF7 - $BFA5 | 無 I |
| K | $BFA6 - $C0AB | |
| L | $C0AC - $C2E7 | |
| M | $C2E8 - $C4C2 | |
| N | $C4C3 - $C5B5 | |
| O | $C5B6 - $C5BD | |
| P | $C5BE - $C6D9 | |
| Q | $C6DA - $C8BA | |
| R | $C8BB - $C8F5 | |
| S | $C8F6 - $CBF9 | |
| T | $CBFA - $CDD9 | |
| W | $CDDA - $CEF3 | 無 U, V |
| X | $CEF4 - $D188 | |
| Y | $D1B9 - $D4D0 | |
| Z | $D4D1 - $D7F9 |
unit PinyinSearch;
interface
uses
SysUtils, Classes;
{ 取得單一漢字的拼音首字母 (大寫)
參數: hzchar - 兩個字元組成的 AnsiChar (Big5 雙位元組)
回傳: 'A'..'Z' 或 #0 (非漢字) }
function GetPYIndexChar(const hzchar: string): Char;
{ 在字串列表中檢索符合拼音首字碼字串的項目
參數:
SourceStrs - 待檢索資料來源 (每項為完整字串)
PYIndexStr - 檢索鍵值 (如 "zgrmyh"),支援 ? 通配符
回傳: 符合項目以 #13 分隔的字串 }
function SearchByPYIndexStr(SourceStrs: TStrings; const PYIndexStr: string): string;
implementation
function GetPYIndexChar(const hzchar: string): Char;
var
Code: Word;
begin
Result := #0;
if Length(hzchar) < 2 then Exit;
// 組合 Big5 雙位元組內碼: 高位元組 * 256 + 低位元組
Code := Word(Byte(hzchar[1])) shl 8 + Byte(hzchar[2]);
case Code of
$B0A1..$B0C4: Result := 'A';
$B0C5..$B2C0: Result := 'B';
$B2C1..$B4ED: Result := 'C';
$B4EE..$B6E9: Result := 'D';
$B6EA..$B7A1: Result := 'E';
$B7A2..$B8C0: Result := 'F';
$B8C1..$B9FD: Result := 'G';
$B9FE..$BBF6: Result := 'H';
$BBF7..$BFA5: Result := 'J';
$BFA6..$C0AB: Result := 'K';
$C0AC..$C2E7: Result := 'L';
$C2E8..$C4C2: Result := 'M';
$C4C3..$C5B5: Result := 'N';
$C5B6..$C5BD: Result := 'O';
$C5BE..$C6D9: Result := 'P';
$C6DA..$C8BA: Result := 'Q';
$C8BB..$C8F5: Result := 'R';
$C8F6..$CBF9: Result := 'S';
$CBFA..$CDD9: Result := 'T';
$CDDA..$CEF3: Result := 'W';
$CEF4..$D188: Result := 'X';
$D1B9..$D4D0: Result := 'Y';
$D4D1..$D7F9: Result := 'Z';
else
Result := #0;
end;
end;
function SearchByPYIndexStr(SourceStrs: TStrings; const PYIndexStr: string): string;
var
i, j: Integer;
hzchar: string;
Matched: Boolean;
UpperKey: string;
begin
Result := '';
UpperKey := UpperCase(PYIndexStr);
for i := 0 to SourceStrs.Count - 1 do
begin
Matched := True;
// 檢查每個首字碼字元
for j := 1 to Length(UpperKey) do
begin
// 取得來源字串第 j 個漢字 (雙位元組)
if (2*j - 1 <= Length(SourceStrs[i])) and (2*j <= Length(SourceStrs[i])) then
hzchar := SourceStrs[i][2*j - 1] + SourceStrs[i][2*j]
else
begin
Matched := False;
Break;
end;
// 通配符 ? 匹配任意首字母
if (UpperKey[j] <> '?') and (UpperKey[j] <> GetPYIndexChar(hzchar)) then
begin
Matched := False;
Break;
end;
end;
if Matched then
begin
if Result = '' then
Result := SourceStrs[i]
else
Result := Result + #13 + SourceStrs[i];
end;
end;
end;
end.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, PinyinSearch;
type
TForm1 = class(TForm)
EditSearch: TEdit; // 輸入拼音首字碼
ListBoxSource: TListBox; // 來源資料
ListBoxResult: TListBox; // 檢索結果
procedure EditSearchChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
// 載入測試資料
ListBoxSource.Items.Add('中國人民銀行');
ListBoxSource.Items.Add('中國工商銀行');
ListBoxSource.Items.Add('中國農業銀行');
ListBoxSource.Items.Add('中國建設銀行');
ListBoxSource.Items.Add('交通銀行');
ListBoxSource.Items.Add('招商銀行');
ListBoxSource.Items.Add('浦發銀行');
ListBoxSource.Items.Add('民生銀行');
ListBoxSource.Items.Add('興業銀行');
ListBoxSource.Items.Add('光大銀行');
end;
procedure TForm1.EditSearchChange(Sender: TObject);
var
ResultStr: string;
List: TStringList;
begin
ResultStr := SearchByPYIndexStr(ListBoxSource.Items, EditSearch.Text);
ListBoxResult.Items.Clear;
if ResultStr <> '' then
begin
List := TStringList.Create;
try
List.Text := ResultStr;
ListBoxResult.Items.Assign(List);
finally
List.Free;
end;
end;
end;
end.
?:匹配任意單一首字母zg?myh 可匹配 中國人民銀行 (z g r m y h) 和 中國農業銀行 (z g n y h) - 注意長度需一致* 匹配任意長度| 編碼 | 適用性 | 處理方式 |
|---|---|---|
| Big5 (繁體中文) | 完美適用 | 原始碼直接使用 |
| GB2312/GBK (簡體中文) | 內碼順序不同,不可直接用 | 需建立 GB 專用對應表,或轉 Unicode 後查表 |
| Unicode (Delphi 2009+) | 無固定內碼順序 | 建議:轉換為拼音庫 (如 pinyin4delphi) 或使用 Windows API GetPhonetic |