首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 實現中文姓名拆分姓氏與名字:支持複姓、單名、邊界處理

     編輯:PHP 綜合知識

中文姓名結構:姓氏 (1-2 字) + 名字 (1-2 字)。難點在於**複姓識別**(歐陽、司馬、上官等)與**單名邊界判斷**。本文提供生產級 `splitChineseName()` 函數,內置 81 個常見複姓,處理 2-4 字姓名全覆蓋。

核心函數代碼

<?php
/**
 * 中文姓名拆分:姓氏 + 名字
 *
 * @param string $fullName UTF-8 編碼姓名
 * @return array [surname, givenName]
 */
function splitChineseName(string $fullName): array {
    // 81 個常見複姓 (來源: 百家姓、現代漢語詞典)
    static $compoundSurnames = [
        '歐陽','太史','端木','上官','司馬','東方','獨孤','南宮','萬俟','聞人',
        '夏侯','諸葛','尉遲','公羊','赫連','澹台','皇甫','宗政','濮陽','公冶',
        '太叔','申屠','公孫','慕容','仲孫','鐘離','長孫','宇文','城池','司徒',
        '鮮于','司空','汝嫣','閭丘','子車','亓官','司寇','巫馬','公西','顓孫',
        '壤駟','公良','漆雕','樂正','宰父','穀梁','拓跋','夾谷','軒轅','令狐',
        '段干','百里','呼延','東郭','南門','羊舌','微生','公戶','公玉','公儀',
        '梁丘','公仲','公上','公門','公山','公堅','左丘','公伯','西門','公祖',
        '第五','公乘','貫丘','公皙','南榮','東裡','東宮','仲長','子書','子桑',
        '即墨','達奚','褚師'
    ];

    $len = mb_strlen($fullName, 'UTF-8');
    $surname = '';
    $givenName = '';

    if ($len >= 3) {
        // 3-4 字姓名:優先匹配複姓
        $firstTwo = mb_substr($fullName, 0, 2, 'UTF-8');
        if (in_array($firstTwo, $compoundSurnames, true)) {
            $surname = $firstTwo;
            $givenName = mb_substr($fullName, 2, null, 'UTF-8');
        } else {
            // 單姓
            $surname = mb_substr($fullName, 0, 1, 'UTF-8');
            $givenName = mb_substr($fullName, 1, null, 'UTF-8');
        }
    } elseif ($len === 2) {
        // 2 字姓名:單姓 + 單名
        $surname = mb_substr($fullName, 0, 1, 'UTF-8');
        $givenName = mb_substr($fullName, 1, 1, 'UTF-8');
    } else {
        // 1 字或空:視為純姓氏
        $surname = $fullName;
        $givenName = '';
    }

    return [$surname, $givenName];
}
?>

測試用例與輸出

<?php
$testCases = [
    '張三',       // 單姓單名
    '李四',       // 單姓單名
    '王小明',     // 單姓雙名
    '劉德華',     // 單姓雙名
    '歐陽修',     // 複姓單名
    '司馬光',     // 複姓單名
    '諸葛亮',     // 複姓單名
    '上官婉兒',   // 複姓雙名
    '慕容雪',     // 複姓單名
    '長孫無忌',   // 複姓雙名
    '趙',         // 單字
    '',           // 空
];

foreach ($testCases as $name) {
    list($surname, $givenName) = splitChineseName($name);
    echo sprintf("%-10s → 姓: %-6s 名: %s\n", $name, $surname, $givenName);
}

/* 輸出:
張三       → 姓: 張     名: 三
李四       → 姓: 李     名: 四
王小明     → 姓: 王     名: 小明
劉德華     → 姓: 劉     名: 德華
歐陽修     → 姓: 歐陽   名: 修
司馬光     → 姓: 司馬   名: 光
諸葛亮     → 姓: 諸葛   名: 亮
上官婉兒   → 姓: 上官   名: 婉兒
慕容雪     → 姓: 慕容   名: 雪
長孫無忌   → 姓: 長孫   名: 無忌
趙         → 姓: 趙     名: 
           → 姓:       名: 
*/
?>

擴展:支持生僻複姓動態加載

<?php
function loadCompoundSurnames(string $filePath): array {
    if (!is_file($filePath)) return [];
    $content = file_get_contents($filePath);
    $lines = array_filter(array_map('trim', explode("\n", $content)));
    return array_values($lines);
}

// 使用
$customSurnames = loadCompoundSurnames('/path/to/compound_surnames.txt');
// 合併到靜態數組 (需修改函數接收參數或使用全局變量)

邊界情況與限制說明

情況處理邏輯準確性
3字姓名,前2字非複姓 (如「王小明」)單姓「王」+ 雙名「小明」✓ 正確
3字姓名,前2字是複姓 (如「歐陽修」)複姓「歐陽」+ 單名「修」✓ 正確
4字姓名,前2字非複姓 (如「劉德華」)單姓「劉」+ 雙名「德華」✓ 正確
4字姓名,前2字是複姓 (如「上官婉兒」)複姓「上官」+ 雙名「婉兒」✓ 正確
生僻複姓不在庫中 (如「第五言」)誤判為單姓「第」+ 名「五言」⚠ 需擴充庫
非漢字姓名 (英文、少數民族)不適用,需單獨邏輯✗ 不支持
姓名含「·」分隔符 (如「烏茲別克·阿里」)需預處理分割⚠ 需擴展

性能優化建議

  • 靜態變量緩存複姓數組:避免重複創建 (代碼中已用 `static`)。
  • 預編譯為 Trie 樹**:超大複姓庫 (千級) 時,`in_array` O(N) → Trie O(長度)。
  • 批量處理用 array_map**:`array_map('splitChineseName', $nameList)`。

現代替代:第三方庫

  • overtrue/pinyin:`composer require overtrue/pinyin`,內置姓名拆分、拼音轉換。
  • jiangmiao/name-parser:專注姓名解析,支持複姓、少數民族、英文名。

總結

中文姓名拆分核心是**複姓識別**。本函數內置 81 常見複姓,正確處理 2-4 字姓名,邊界情況清晰。生產環境建議:維護業務專屬複姓庫 (含生僻複姓)、異常情況記錄日誌人工覆核、集成成熟第三方庫**。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved