不需要自行撰寫 API 程式碼來以自然排序法排序關聯式陣列的鍵值。PHP 的內建函式(natsort 以外)就可以勝任這項工作。
<?php
uksort($myArray, "strnatcmp");
?>
(PHP 4, PHP 5, PHP 7, PHP 8)
natsort — 使用「自然排序」演算法排序陣列
此函式實作了一種排序演算法,它以人類的方式對字母數字字串進行排序,同時保持鍵/值關聯。這被描述為「自然排序」。此演算法與一般電腦字串排序演算法(用於 sort() 中)之間的差異,可以在下面的範例中看到。
備註:
如果兩個成員比較結果相等,它們會保留原始順序。在 PHP 8.0.0 之前,它們在排序後陣列中的相對順序未定義。
備註:
重設陣列的內部指標到第一個元素。
array
輸入的陣列。
總是回傳 true
。
範例 #1 natsort() 範例示範基本用法
<?php
$array1 = $array2 = array("img12.png", "img10.png", "img2.png", "img1.png");
asort($array1);
echo "標準排序\n";
print_r($array1);
natsort($array2);
echo "\n自然排序\n";
print_r($array2);
?>
上述範例將輸出:
Standard sorting Array ( [3] => img1.png [1] => img10.png [0] => img12.png [2] => img2.png ) Natural order sorting Array ( [3] => img1.png [2] => img2.png [1] => img10.png [0] => img12.png )
更多資訊請參考:Martin Pool 的 » 自然順序字串比較 頁面。
範例 #2 natsort() 範例示範潛在的陷阱
<?php
echo "負數\n";
$negative = array('-5','3','-2','0','-1000','9','1');
print_r($negative);
natsort($negative);
print_r($negative);
echo "零填充\n";
$zeros = array('09', '8', '10', '009', '011', '0');
print_r($zeros);
natsort($zeros);
print_r($zeros);
?>
上述範例將輸出:
Negative numbers Array ( [0] => -5 [1] => 3 [2] => -2 [3] => 0 [4] => -1000 [5] => 9 [6] => 1 ) Array ( [2] => -2 [0] => -5 [4] => -1000 [3] => 0 [6] => 1 [1] => 3 [5] => 9 ) Zero padding Array ( [0] => 09 [1] => 8 [2] => 10 [3] => 009 [4] => 011 [5] => 0 ) Array ( [5] => 0 [1] => 8 [3] => 009 [0] => 09 [2] => 10 [4] => 011 )
不需要自行撰寫 API 程式碼來以自然排序法排序關聯式陣列的鍵值。PHP 的內建函式(natsort 以外)就可以勝任這項工作。
<?php
uksort($myArray, "strnatcmp");
?>
關於反向自然排序… 或許更簡單的做法是
function strrnatcmp ($a, $b) {
return strnatcmp ($b, $a);
}
請注意 5.2.10 版本的新行為。
請參考以下範例
<?php
$array = array('1 bis', '10 ter', '0 PHP', '0', '01', '01 Ver', '0 ', '1 ', '1');
natsort($array);
echo '<pre>';
print_r($array);
echo '</pre>';
?>
5.2.6-1 的輸出結果為
陣列
(
[3] => 0
[6] => 0
[2] => 0 OP
[4] => 01
[5] => 01 Ver
[8] => 1
[7] => 1
[0] => 1 bis
[1] => 10 ter
)
5.2.10 的輸出結果為
陣列
(
[6] => 0
[3] => 0
[8] => 1
[4] => 01
[7] => 1
[5] => 01 Ver
[0] => 1 bis
[1] => 10 ter
[2] => 0 OP
)
您好
對於想要以自然排序法排序二維陣列中每個子陣列的第一個元素的人來說,以下幾行程式碼應該可以完成這項工作。
<?php
函式 natsort2d(&$aryInput) {
$aryTemp = $aryOut = array();
foreach ($aryInput as $key=>$value) {
reset($value);
$aryTemp[$key]=current($value);
}
natsort($aryTemp);
foreach ($aryTemp as $key=>$value) {
$aryOut[] = $aryInput[$key];
}
$aryInput = $aryOut;
}
?>
反向自然排序 (Reverse Natsort)
函式 rnatsort($a, $b) {
返回 -1 * strnatcmp($a, $b);
}
usort($arr, "rnatsort");
在有限的測試下,natsort() 似乎可以很好地處理 IP 位址。就我的需求而言,它的程式碼比我之前使用的 ip2long()/long2ip() 轉換少得多。
要製作反向函式,您可以簡單地
函式 rnatsort(&$a){
natsort($a);
$a = array_reverse($a, true);
}
我因為天真地使用這個功能而被困住了——嘗試對數位相機的影像檔名列表進行排序,其中檔名是前導零填充的(例如 DSCF0120.jpg),將無法正確排序。
也許可以修改範例來展示這種行為
(例如,將陣列設定為 -img0120.jpg','IMG0.png', 'img0012.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png)
如果範例中沒有使用圖片,我第一次就會正確編碼!
注意:負數。
<?php
$a = array(-5,-2,3,9);
natsort($a);
print_r($a);
?>
將輸出
陣列 ( [1] => -2 [0] => -5 [2] => 3 [3] => 9 )
這讓我浪費了許多寶貴的青春……如果所有數字的小數位數不同,natsort() 就會有錯誤。
(php 5.6.4-4ubuntu6.2)
<?php
$不同小數位數的值 = array('D'=>'13.59', '14.6' => '14.6', 'C-' => '14.19');
natsort($a);
var_dump($a);
/* 顯示結果
array(3) {
'D' =>
string(5) "13.59"
'14.6' =>
string(4) "14.6" <----------- 排序錯誤
'C-' =>
string(5) "14.19"
}*/
?>
雖然這樣
<?php
$相同小數位數的值 = array('D'=>'13.59', '14.6' => '14.60', 'C-' => '14.19'); natsort($a); var_dump($a);
/* 顯示結果
array(3) {
'D' =>
string(5) "13.59"
'C-' =>
string(5) "14.19"
'14.6' =>
string(5) "14.60" <--------- 這才是正確的位置
}
*/
?>
頁面下方還有另一個 rnatsort 函式,但在我的使用情境中它無法運作。
這樣做的原因
透過陣列的鍵值進行自然排序,但需要反轉順序。
函式 rnatsort ( &$array = array() )
{
$keys = array_keys($array);
natsort($keys);
$total = count($keys) - 1;
$temp1 = array();
$temp2 = array();
// 將原始鍵值賦值給一個鍵值反向的陣列,以便在 krsort() 中使用;
foreach ( $keys as $key )
{
$temp1[$total] = $key;
--$total;
}
ksort($temp1);
// 設定新的陣列,使用 krsort() 的順序和原始陣列的值。
foreach ( $temp1 as $key )
{
$temp2[$key] = $array[$key];
}
$array = $temp2;
}
這個函式非常有用,但在某些情況下,例如,如果您想排序 MySQL 查詢結果,務必記住 MySQL 有內建的排序函式,比使用複雜的 PHP 演算法重新排序結果要快得多,尤其是在處理大型陣列時。
例如:'SELECT * FROM `table` ORDER BY columnName ASC, columnName2 DESC'
除了 justin at redwiredesign dot com 發布的程式碼(我發現它非常有用)之外,這裡還有一個函式可以排序像這樣的複雜陣列
<?
$array['test0'] = array('main' => 'a', 'sub' => 'a');
$array['test2'] = array('main' => 'a', 'sub' => 'b');
$array['test3'] = array('main' => 'b', 'sub' => 'c');
$array['test1'] = array('main' => 'a', 'sub' => 'c');
$array['test4'] = array('main' => 'b', 'sub' => 'a');
$array['test5'] = array('main' => 'b', 'sub' => 'b');
?>
或者
<?
$array[0] = array('main' => 1, 'sub' => 1);
$array[2] = array('main' => 1, 'sub' => 2);
$array[3] = array('main' => 2, 'sub' => 3);
$array[1] = array('main' => 1, 'sub' => 3);
$array[4] = array('main' => 2, 'sub' => 1);
$array[5] = array('main' => 2, 'sub' => 2);
?>
根據一或多個欄位排序。
程式碼
<? $array = array_natsort_list($array,'main','sub'); ?>
會讓 $array 排序成這樣
test0,test2,test1,test4,test5,test3
或者
0,2,1,4,5,3.
你甚至可以傳遞更多值給這個函式,因為它使用可變參數列表。 這個函式會從最後一個排序欄位開始排序,直到第一個排序欄位。
對我來說,這在排序具有子選單,甚至子子選單的選單時非常有用。
我希望它也能幫助你。
以下是函式
<?
function array_natsort_list($array) {
// 從列表末尾開始,處理除了第一個以外的所有參數
for ($i=func_num_args();$i>1;$i--) {
// 取得要排序的欄位
$sort_by = func_get_arg($i-1);
// 清空陣列
$new_array = array();
$temporary_array = array();
// 遍歷原始陣列
foreach($array as $original_key => $original_value) {
// 只儲存值
$temporary_array[] = $original_value[$sort_by];
}
// 根據值排序陣列
natsort($temporary_array);
// 刪除重複值
$temporary_array = array_unique($temporary_array);
// 遍歷暫存陣列
foreach($temporary_array as $temporary_value) {
// 遍歷原始陣列
foreach($array as $original_key => $original_value) {
// 搜尋具有正確值的項目
if($temporary_value == $original_value[$sort_by]) {
// 儲存到新的陣列
$new_array[$original_key] = $original_value;
}
}
}
// 更新原始陣列
$array = $new_array;
}
return $array;
}
?>
$array1 = $array2 = array('IMG0.png', 'img12.png', 'img10.png', 'img2.png', 'img1.png', 'IMG3.png');
natsort($array1);
echo "\n natsort(); \n";
print_r($array1);
sort($array2, SORT_NATURAL);
echo "\n 使用 SORT_NATURAL 選項的 sort()\n";
print_r($array2);
輸出
natsort();
陣列
(
[0] => IMG0.png
[5] => IMG3.png
[4] => img1.png
[3] => img2.png
[2] => img10.png
[1] => img12.png
)
使用 SORT_NATURAL 選項的 sort()
陣列
(
[0] => IMG0.png
[1] => IMG3.png
[2] => img1.png
[3] => img2.png
[4] => img10.png
[5] => img12.png
)
如我們所見,值相同但鍵不同,sort($array1, SORT_NATURAL | SORT_FLAG_CASE); 和 natcasesort($array2) 的結果也一樣
要根據陣列鍵進行自然排序,可以使用 uksort 函式。
<?php
echo "依鍵排序\n";
$smoothie = array('orange' => 1, 'apple' => 1, 'yogurt' => 4, 'banana' => 4);
print_r($smoothie);
uksort( $smoothie, 'strnatcmp');
print_r($smoothie)
?>
輸出
依鍵排序
陣列
(
[橘子] => 1
[蘋果] => 1
[優格] => 4
[香蕉] => 4
)
陣列
(
[蘋果] => 1
[香蕉] => 4
[橘子] => 1
[優格] => 4
)
更多關於 uksort 的資訊請參考 https://php.dev.org.tw/manual/en/function.uksort.php,strnatcmp 的用法請參考 https://php.dev.org.tw/strnatcmp。
這是一個方便的函式,可以用自然排序法依據一或多個欄位排序陣列
<?php
// 範例:$records = columnSort($records, array('name', 'asc', 'addres', 'desc', 'city', 'asc'));
$globalMultisortVar = array();
function columnSort($recs, $cols) {
global $globalMultisortVar;
$globalMultisortVar = $cols;
usort($recs, 'multiStrnatcmp');
return($recs);
}
function multiStrnatcmp($a, $b) {
global $globalMultisortVar;
$cols = $globalMultisortVar;
$i = 0;
$result = 0;
while ($result == 0 && $i < count($cols)) {
$result = ($cols[$i + 1] == 'desc' ? strnatcmp($b[$cols[$i]], $a[$cols[$i]]) : $result = strnatcmp($a[$cols[$i]], $b[$cols[$i]]));
$i+=2;
}
return $result;
}
?>
敬禮,
- John
natsort 的處理方式在遇到零填充時可能與您的預期不同,這裡有一個簡單的例子。
<?php
$array = array('09', '8', '10', '009', '011');
natsort($array);
?>
/*
陣列
(
[3] => 009
[4] => 011
[0] => 09
[1] => 8
[2] => 10
)
*/
mbirth at webwriters dot de 發布的這段實用程式碼少了一點東西
<?php
函式 natsort2d(&$aryInput) {
$aryTemp = $aryOut = array();
foreach ($aryInput as $key=>$value) {
reset($value);
$aryTemp[$key]=current($value);
}
natsort($aryTemp);
foreach ($aryTemp as $key=>$value) {
$aryOut[$key] = $aryInput[$key];
// --------^^^^ 如果您希望保留鍵值,請加上這行!
}
$aryInput = $aryOut;
}
?>
如同其他說明所提到的,natsort() 並_不_總是會返回預期的排序順序。當使用小數或 0 填補時,它似乎特別容易出錯。我已針對此問題提交了錯誤報告
https://bugs.php.net/bug.php?id=74672