数组排序是 PHP 中常见的数据处理操作,PHP 提供了丰富的排序函数来满足不同的排序需求,包括升序、降序、按键排序、按值排序等。
PHP 提供了多种数组排序函数,可以根据不同的需求选择合适的排序方法:
对索引数组进行升序排列
按值排序,重置键名
对索引数组进行降序排列
按值排序,重置键名
根据关联数组的值进行升序排列
保持键值关联
根据关联数组的值进行降序排列
保持键值关联
根据关联数组的键进行升序排列
按键名排序
根据关联数组的键进行降序排列
按键名排序
| 函数名 | 排序依据 | 排序顺序 | 保持键名 | 适用数组类型 |
|---|---|---|---|---|
| sort() | 值 | 升序 | 否 | 索引数组 |
| rsort() | 值 | 降序 | 否 | 索引数组 |
| asort() | 值 | 升序 | 是 | 关联数组 |
| arsort() | 值 | 降序 | 是 | 关联数组 |
| ksort() | 键 | 升序 | 是 | 关联数组 |
| krsort() | 键 | 降序 | 是 | 关联数组 |
sort() 函数对数组按值进行升序排序,并重新分配数字索引。
<?php
$cars = array("Volvo", "BMW", "Toyota");
echo "排序前: ";
print_r($cars);
sort($cars);
echo "排序后: ";
print_r($cars);
?>
排序前: Array
(
[0] => Volvo
[1] => BMW
[2] => Toyota
)
排序后: Array
(
[0] => BMW
[1] => Toyota
[2] => Volvo
)
<?php
$numbers = array(4, 6, 2, 22, 11);
echo "排序前: ";
print_r($numbers);
sort($numbers);
echo "排序后: ";
print_r($numbers);
// 注意:键名被重新索引
echo "第一个元素: " . $numbers[0];
?>
注意: sort() 函数会重新分配数字索引,原来的键名将丢失。如果需要保持键值关联,请使用 asort()。
rsort() 函数对数组按值进行降序排序,并重新分配数字索引。
<?php
$fruits = array("apple", "banana", "cherry", "date");
echo "排序前: ";
print_r($fruits);
rsort($fruits);
echo "排序后: ";
print_r($fruits);
?>
<?php
$scores = array(85, 92, 78, 96, 88);
echo "分数排序前: ";
print_r($scores);
rsort($scores);
echo "分数排序后(降序): ";
print_r($scores);
// 实际应用:显示排名
echo "分数排名: <br>";
foreach ($scores as $rank => $score) {
echo ($rank + 1) . ". " . $score . "分<br>";
}
?>
asort() 函数对关联数组按值进行升序排序,并保持键值关联。
<?php
$age = array("Peter" => 35, "Ben" => 37, "Joe" => 43, "Alice" => 28);
echo "排序前: ";
print_r($age);
asort($age);
echo "按年龄升序排序: ";
print_r($age);
// 遍历排序后的数组
foreach ($age as $name => $ageValue) {
echo "$name 的年龄是 $ageValue<br>";
}
?>
<?php
$products = array(
"笔记本电脑" => 4500,
"智能手机" => 3200,
"平板电脑" => 2800,
"智能手表" => 1200
);
echo "产品价格排序前: <br>";
foreach ($products as $product => $price) {
echo "$product: ¥$price<br>";
}
asort($products);
echo "<br>按价格升序排序: <br>";
foreach ($products as $product => $price) {
echo "$product: ¥$price<br>";
}
?>
arsort() 函数对关联数组按值进行降序排序,并保持键值关联。
<?php
$age = array("Peter" => 35, "Ben" => 37, "Joe" => 43, "Alice" => 28);
echo "排序前: ";
print_r($age);
arsort($age);
echo "按年龄降序排序: ";
print_r($age);
?>
<?php
$studentScores = array(
"张三" => 85,
"李四" => 92,
"王五" => 78,
"赵六" => 96,
"钱七" => 88
);
arsort($studentScores);
echo "学生成绩排名(从高到低): <br>";
$rank = 1;
foreach ($studentScores as $student => $score) {
echo "$rank. $student: $score 分<br>";
$rank++;
}
?>
ksort() 函数对关联数组按键进行升序排序。
<?php
$countryCodes = array(
"CN" => "中国",
"US" => "美国",
"JP" => "日本",
"UK" => "英国",
"DE" => "德国"
);
echo "排序前: ";
print_r($countryCodes);
ksort($countryCodes);
echo "按国家代码升序排序: ";
print_r($countryCodes);
?>
<?php
$monthlyData = array(
"March" => 1500,
"January" => 1200,
"December" => 1800,
"June" => 1400,
"September" => 1600
);
echo "月度数据(按键排序前): <br>";
foreach ($monthlyData as $month => $value) {
echo "$month: $value<br>";
}
ksort($monthlyData);
echo "<br>按月份名称升序排序: <br>";
foreach ($monthlyData as $month => $value) {
echo "$month: $value<br>";
}
?>
krsort() 函数对关联数组按键进行降序排序。
<?php
$productCategories = array(
"A100" => "电子产品",
"B200" => "服装",
"C300" => "食品",
"D400" => "家居"
);
echo "排序前: ";
print_r($productCategories);
krsort($productCategories);
echo "按分类代码降序排序: ";
print_r($productCategories);
?>
<?php
$versions = array(
"v1.0" => "初始版本",
"v2.1" => "功能更新",
"v1.5" => "小版本更新",
"v3.0" => "重大更新"
);
krsort($versions);
echo "版本号降序排序(最新版本在前): <br>";
foreach ($versions as $version => $description) {
echo "$version: $description<br>";
}
?>
PHP 还提供了自然排序算法,可以更人性化地处理包含数字的字符串排序。
<?php
$files = array("img12.png", "img10.png", "img2.png", "img1.png");
echo "原始数组: ";
print_r($files);
// 常规排序
$standardSort = $files;
sort($standardSort);
echo "常规排序: ";
print_r($standardSort);
// 自然排序
$naturalSort = $files;
natsort($naturalSort);
echo "自然排序: ";
print_r($naturalSort);
?>
<?php
$mixedCase = array("IMG1.png", "img12.png", "IMG10.png", "img2.png");
echo "原始数组: ";
print_r($mixedCase);
natcasesort($mixedCase);
echo "不区分大小写的自然排序: ";
print_r($mixedCase);
?>
PHP 允许使用自定义比较函数进行排序,提供了更大的灵活性。
<?php
$products = array(
array("name" => "笔记本电脑", "price" => 4500, "weight" => 2.5),
array("name" => "智能手机", "price" => 3200, "weight" => 0.2),
array("name" => "平板电脑", "price" => 2800, "weight" => 0.6),
array("name" => "智能手表", "price" => 1200, "weight" => 0.1)
);
// 按价格排序
usort($products, function($a, $b) {
return $a['price'] - $b['price'];
});
echo "按价格升序排序: <br>";
foreach ($products as $product) {
echo $product['name'] . ": ¥" . $product['price'] . "<br>";
}
echo "<br>";
// 按重量排序
usort($products, function($a, $b) {
return $a['weight'] * 100 - $b['weight'] * 100; // 避免浮点数比较问题
});
echo "按重量升序排序: <br>";
foreach ($products as $product) {
echo $product['name'] . ": " . $product['weight'] . "kg<br>";
}
?>
<?php
$data = array(
"item_10" => "值10",
"item_2" => "值2",
"item_1" => "值1",
"item_20" => "值20"
);
// 按数字部分排序
uksort($data, function($a, $b) {
$numA = intval(str_replace('item_', '', $a));
$numB = intval(str_replace('item_', '', $b));
return $numA - $numB;
});
echo "按键中数字部分排序: <br>";
foreach ($data as $key => $value) {
echo "$key: $value<br>";
}
?>
对于多维数组,可以使用自定义排序函数来实现复杂的排序需求。
<?php
$students = array(
array("name" => "张三", "age" => 20, "score" => 85),
array("name" => "李四", "age" => 22, "score" => 92),
array("name" => "王五", "age" => 20, "score" => 78),
array("name" => "赵六", "age" => 21, "score" => 85),
array("name" => "钱七", "age" => 22, "score" => 88)
);
// 按年龄升序,同年龄按分数降序排序
usort($students, function($a, $b) {
// 先按年龄比较
if ($a['age'] != $b['age']) {
return $a['age'] - $b['age'];
}
// 年龄相同,按分数降序
return $b['score'] - $a['score'];
});
echo "学生数据排序(年龄升序,同年龄分数降序): <br>";
foreach ($students as $student) {
echo "姓名: " . $student['name'] . ", 年龄: " . $student['age'] . ", 分数: " . $student['score'] . "<br>";
}
?>
<?php
$products = array(
array("category" => "电子产品", "name" => "iPhone", "price" => 6999, "rating" => 4.5),
array("category" => "电子产品", "name" => "iPad", "price" => 3299, "rating" => 4.3),
array("category" => "服装", "name" => "T恤", "price" => 99, "rating" => 4.2),
array("category" => "服装", "name" => "牛仔裤", "price" => 299, "rating" => 4.4),
array("category" => "家居", "name" => "台灯", "price" => 159, "rating" => 4.1)
);
// 按分类字母顺序,同分类按评分降序排序
usort($products, function($a, $b) {
// 先按分类比较
$categoryCompare = strcmp($a['category'], $b['category']);
if ($categoryCompare != 0) {
return $categoryCompare;
}
// 同分类按评分降序
return $b['rating'] * 10 - $a['rating'] * 10; // 避免浮点数比较问题
});
echo "产品数据排序: <br>";
foreach ($products as $product) {
echo "分类: " . $product['category'] . ", 名称: " . $product['name'] .
", 价格: ¥" . $product['price'] . ", 评分: " . $product['rating'] . "<br>";
}
?>
<?php
// 模拟电子商务产品数据
$products = array(
array("id" => 1, "name" => "iPhone 14", "price" => 5999, "sales" => 1500, "rating" => 4.7),
array("id" => 2, "name" => "Samsung Galaxy", "price" => 4999, "sales" => 1200, "rating" => 4.5),
array("id" => 3, "name" => "小米手机", "price" => 2999, "sales" => 2000, "rating" => 4.6),
array("id" => 4, "name" => "华为Mate", "price" => 4599, "sales" => 1800, "rating" => 4.8)
);
// 价格排序函数
function sortByPrice($products, $order = 'asc') {
usort($products, function($a, $b) use ($order) {
if ($order === 'asc') {
return $a['price'] - $b['price'];
} else {
return $b['price'] - $a['price'];
}
});
return $products;
}
// 销量排序函数
function sortBySales($products, $order = 'desc') {
usort($products, function($a, $b) use ($order) {
if ($order === 'asc') {
return $a['sales'] - $b['sales'];
} else {
return $b['sales'] - $a['sales'];
}
});
return $products;
}
// 评分排序函数
function sortByRating($products, $order = 'desc') {
usort($products, function($a, $b) use ($order) {
if ($order === 'asc') {
return $a['rating'] * 10 - $b['rating'] * 10;
} else {
return $b['rating'] * 10 - $a['rating'] * 10;
}
});
return $products;
}
// 测试不同的排序方式
echo "=== 按价格升序排序 ===<br>";
$priceSorted = sortByPrice($products, 'asc');
foreach ($priceSorted as $product) {
echo $product['name'] . " - ¥" . $product['price'] . "<br>";
}
echo "<br>=== 按销量降序排序 ===<br>";
$salesSorted = sortBySales($products, 'desc');
foreach ($salesSorted as $product) {
echo $product['name'] . " - 销量: " . $product['sales'] . "<br>";
}
echo "<br>=== 按评分降序排序 ===<br>";
$ratingSorted = sortByRating($products, 'desc');
foreach ($ratingSorted as $product) {
echo $product['name'] . " - 评分: " . $product['rating'] . "<br>";
}
?>
<?php
// 月度销售数据
$monthlySales = array(
"一月" => array("revenue" => 150000, "profit" => 45000, "growth" => 12.5),
"二月" => array("revenue" => 165000, "profit" => 52000, "growth" => 10.0),
"三月" => array("revenue" => 142000, "profit" => 41000, "growth" => 8.5),
"四月" => array("revenue" => 178000, "profit" => 58000, "growth" => 15.2)
);
// 按收入排序
uasort($monthlySales, function($a, $b) {
return $b['revenue'] - $a['revenue'];
});
echo "=== 按收入降序排序 ===<br>";
foreach ($monthlySales as $month => $data) {
echo "$month: 收入 ¥" . number_format($data['revenue']) .
", 利润 ¥" . number_format($data['profit']) .
", 增长率 " . $data['growth'] . "%<br>";
}
echo "<br>";
// 按增长率排序
uasort($monthlySales, function($a, $b) {
return $b['growth'] * 100 - $a['growth'] * 100;
});
echo "=== 按增长率降序排序 ===<br>";
foreach ($monthlySales as $month => $data) {
echo "$month: 增长率 " . $data['growth'] . "%, 收入 ¥" .
number_format($data['revenue']) . "<br>";
}
?>
排序性能优化建议:
sort() 系列函数通常比自定义排序函数更快<?php
$numbers = array(10, 2, 35, 4, 15);
// 常规排序
sort($numbers);
echo "常规排序: ";
print_r($numbers);
// 使用排序标志
$numbers = array(10, 2, 35, 4, 15);
sort($numbers, SORT_NUMERIC);
echo "数值排序: ";
print_r($numbers);
$strings = array("10", "2", "35", "4", "15");
sort($strings, SORT_STRING);
echo "字符串排序: ";
print_r($strings);
// 自然排序标志
$files = array("img12.png", "img10.png", "img2.png", "img1.png");
sort($files, SORT_NATURAL);
echo "自然排序: ";
print_r($files);
?>
<?php
// 错误1:在自定义排序函数中返回布尔值
$numbers = array(3, 1, 4, 1, 5);
/*
usort($numbers, function($a, $b) {
return $a > $b; // 错误:应该返回 -1, 0, 1
});
*/
// 正确做法:返回整数
usort($numbers, function($a, $b) {
if ($a == $b) return 0;
return ($a < $b) ? -1 : 1;
});
// 错误2:忽略浮点数比较的精度问题
$prices = array(10.1, 10.01, 10.001);
usort($prices, function($a, $b) {
// return $a - $b; // 可能产生精度问题
return ($a * 1000) - ($b * 1000); // 更好的方式
});
// 错误3:在排序过程中修改原数组
$data = array(3, 1, 4);
sort($data);
// 现在 $data 已经被修改,原始顺序丢失
?>
<?php
$numbers = array(3, 1, 4, 1, 5);
// PHP 7+ 使用太空船运算符
usort($numbers, function($a, $b) {
return $a <=> $b; // 升序排序
});
echo "升序排序: ";
print_r($numbers);
// 降序排序
usort($numbers, function($a, $b) {
return $b <=> $a; // 降序排序
});
echo "降序排序: ";
print_r($numbers);
// 多维数组排序示例
$students = array(
array("name" => "张三", "score" => 85),
array("name" => "李四", "score" => 92),
array("name" => "王五", "score" => 78)
);
usort($students, function($a, $b) {
return $b['score'] <=> $a['score']; // 按分数降序
});
echo "学生按分数降序排序: <br>";
foreach ($students as $student) {
echo $student['name'] . ": " . $student['score'] . "分<br>";
}
?>
<=> 可以简化比较逻辑