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

PHP strnatcmp() 自然排序比較:解決「10 小於 2」的字串排序難題

     編輯:PHP 綜合知識

問題背景:標準字串比較的陷阱

標準 strcmp 按 ASCII 碼逐字元比較,導致數字字串排序違反直覺:

$files = ['2.jpg', '10.jpg', '1.jpg'];
sort($files); // 標準排序
print_r($files);
// Array([0]=>10.jpg [1]=>1.jpg [2]=>2.jpg) // 10 排在 1 前面!

strnatcmp:自然排序演算法

int strnatcmp(string $str1, string $str2)
  • 識別字串中的數字區段,按數值大小比較而非字元碼。
  • 區分大小寫;不分大小寫版本為 strnatcasecmp。
  • 回傳值同 strcmp:0 相等、<0 較小、>0 較大。

實測比較

$a = '2.jpg';  $b = '10.jpg';
$c = 'jb51.net_1'; $d = 'JB51.NET_2';

echo strcmp($a, $b);       // 1  (標準:'1' < '2')
echo strnatcmp($a, $b);    // -1 (自然:2 < 10)

echo strcmp($c, $d);       // 1  (標準:'J' < 'j')
echo strnatcmp($c, $d);    // 1  (自然:_1 < _2,大小寫仍敏感)

自然排序陣列:natsort / natcasesort

$files = ['2.jpg', '10.jpg', '1.jpg', '20.jpg', '3.jpg'];
natsort($files); // 保留鍵名
print_r($files);
// Array([2]=>1.jpg [0]=>2.jpg [4]=>3.jpg [1]=>10.jpg [3]=>20.jpg)

// 不分大小寫
$files2 = ['a1.txt', 'A10.txt', 'A2.txt'];
natcasesort($files2);

適用場景與限制

場景推薦函式備註
檔案名稱排序(含數字)natsort最常見用途
版本號比較(v1.2 vs v1.10)version_compare專門處理版本號格式
一般字串自然排序strnatcmp + usort自訂比較邏輯
多位元組字串不支援UTF-8 中文數字混排會錯誤

進階:自訂自然排序比較函式

function natcmp_utf8($a, $b) {
    // 簡易版:將連續數字轉為固定寬度零填充再 strcmp
    $pad = function($m) { return sprintf('%010d', $m[0]); };
    $a = preg_replace_callback('/\d+/', $pad, $a);
    $b = preg_replace_callback('/\d+/', $pad, $b);
    return strcmp($a, $b);
}
usort($utf8Files, 'natcmp_utf8');

效能考量

  • strnatcmp 為 C 實作,速度極快,大量排序時優於 PHP 層回呼。
  • 若資料量極大(>10萬筆),考慮在資料庫層用 ORDER BY CAST(SUBSTRING_INDEX(name, '.', 1) AS UNSIGNED) 等 SQL 技巧預排序。

總結

strnatcmp / natsort 是處理「含數字字串排序」的利器,完美解決 10 < 2 的反直覺問題。記住:大小寫敏感、不支援多位元組,中文環境需自行轉碼或改用 Collator (intl 擴充) 進行本地化排序。

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