當前位置: 首頁> 最新文章列表> 如何結合strnatcasecmp 與array_map 對數組中的字符串進行統一格式化?

如何結合strnatcasecmp 與array_map 對數組中的字符串進行統一格式化?

gitbox 2025-05-27

在日常PHP 編程中,我們經常需要對字符串數組進行排序,但默認的字典序排序( sortusort等)並不能很好地處理帶有數字的字符串。比如img1.png , img2.png , img10.png這樣的文件名,如果用普通的字符串比較,排序結果會是img1.png , img10.png , img2.png ,顯然不符合人類的自然排序習慣。

為了實現“自然排序”,PHP 提供了strnatcmpstrnatcasecmp函數,分別對應區分大小寫和不區分大小寫的自然排序。
另外,當我們對數組排序時,常常還需要對數組中的每個元素統一格式化,比如全部轉小寫或去掉多餘空格,這時候可以用array_map來實現。

本文將介紹如何將這兩個工具結合起來,對數組中的字符串進行統一格式化後,再進行自然排序。

核心步驟

1??準備數據數組<br> 我們以一組文件名為例

$files = ['Img10.png', 'img2.png', 'IMG1.png', 'img20.png', 'img11.png'];

2??使用array_map 格式化元素<br> 假設我們想把它們全部轉為小寫

$formattedFiles = array_map('strtolower', $files);

如果要更複雜的處理(比如去空格、統一擴展名),可以寫成匿名函數:

 $formattedFiles = array_map(function($item) {
    return strtolower(trim($item));
}, $files);

3??自定義排序函數
PHP 的usort允許我們用自定義函數排序:

 usort($formattedFiles, 'strnatcasecmp');

注意: strnatcasecmp是一個比較函數,而不是直接用於排序的函數。

完整示例代碼

<?php
$files = ['Img10.png', 'img2.png', 'IMG1.png', 'img20.png', 'img11.png'];

// 第一步:統一格式(轉小寫 + 去空格)
$formattedFiles = array_map(function($item) {
    return strtolower(trim($item));
}, $files);

// 第二步:自然排序(不區分大小寫)
usort($formattedFiles, 'strnatcasecmp');

// 輸出結果
foreach ($formattedFiles as $file) {
    echo $file . "\n";
}
?>

運行結果:

 img1.png
img2.png
img10.png
img11.png
img20.png

更實際的例子:帶URL 的情況

假設我們處理的是一組URL:

 $urls = [
    'https://gitbox.net/File10.html',
    'https://gitbox.net/file2.html',
    'https://gitbox.net/FILE1.html',
    'https://gitbox.net/file20.html',
    'https://gitbox.net/file11.html',
];

我們想按文件名部分排序,可以先提取文件名,再排序:

 <?php
$urls = [
    'https://gitbox.net/File10.html',
    'https://gitbox.net/file2.html',
    'https://gitbox.net/FILE1.html',
    'https://gitbox.net/file20.html',
    'https://gitbox.net/file11.html',
];

// 提取文件名部分並綁定到 URL
$mapped = array_map(function($url) {
    $parts = parse_url($url);
    $file = basename($parts['path']);
    return ['url' => $url, 'file' => strtolower($file)];
}, $urls);

// 按文件名自然排序
usort($mapped, function($a, $b) {
    return strnatcasecmp($a['file'], $b['file']);
});

// 輸出排序後的 URL
foreach ($mapped as $item) {
    echo $item['url'] . "\n";
}
?>

輸出:

 https://gitbox.net/FILE1.html
https://gitbox.net/file2.html
https://gitbox.net/File10.html
https://gitbox.net/file11.html
https://gitbox.net/file20.html