PHP对象数组排序:5分钟从混乱到有序
想象一下:您正在编写一个基于PHP的教育网站,并从数据库中获取了一个学生列表。每个学生都是一个包含姓名、年龄和分数的对象。您需要将它们显示在页面上:先显示年龄最大的,或者相反,年龄最小的。或者,也许需要按字母顺序排序。如果您的数据不是简单的数字数组,而是对象数组,该如何操作?
这个问题是Stack Overflow上最热门的问题之一。成千上万的开发者,从新手到专家,都遇到过“按单一属性对对象数组排序”的任务。今天,我们将一劳永逸地解决它。没有废话,只有生动的示例和清晰的解释。
为什么普通的sort()函数不起作用?
假设我们有一个对象数组 $students:
<?phpclass Student { public $name; public $age; public $score;
public function __construct($name, $age, $score) { $this->name = $name; $this->age = $age; $this->score = $score; }}
$students = [ new Student("安娜", 22, 85), new Student("伊万", 20, 92), new Student("玛丽亚", 23, 78), new Student("彼得", 21, 95)];?>如果您尝试调用 sort($students),PHP会报错或什么都不做。为什么?因为 sort() 只能比较数字和字符串,但不知道如何比较两个对象。您需要告诉它:“按 age 属性比较”或“按 name 比较”。为此,PHP提供了一个专门的函数——usort()。
认识usort():您的主要工具
usort() 函数接受两个参数:数组本身和一个比较函数。这个比较函数必须返回:
- 0,如果元素相等;
- 负数,如果第一个元素小于第二个;
- 正数,如果第一个元素大于第二个。
听起来复杂?实际上很简单。让我们按年龄(升序)对学生进行排序:
<?phpusort($students, function($a, $b) { return $a->age <=> $b->age;});
// 结果:伊万 (20), 彼得 (21), 安娜 (22), 玛丽亚 (23)?>请注意飞船运算符 <=>。它从PHP 7开始引入,使排序代码极其简洁。它比较两个值并返回 -1、0 或 1。这正是 usort() 所需要的。
降序排序:改变符号
想要从大到小排序?只需在飞船运算符中交换操作数的位置:
<?phpusort($students, function($a, $b) { return $b->age <=> $a->age; // 现在b与a比较});
// 结果:玛丽亚 (23), 安娜 (22), 彼得 (21), 伊万 (20)?>或者,等效地,将结果乘以 -1:
<?phpusort($students, function($a, $b) { return -($a->age <=> $b->age);});?>字符串排序(按字母顺序)
如果属性是字符串呢?例如姓名。原理相同,但使用 strcmp() 或 strcasecmp()(用于不区分大小写的比较)代替 <=>:
<?php// 按字母顺序 (A-Z)usort($students, function($a, $b) { return strcmp($a->name, $b->name);});
// 结果:安娜, 伊万, 玛丽亚, 彼得
// 按字母顺序 (Z-A) — 反向顺序usort($students, function($a, $b) { return strcmp($b->name, $a->name);});?>按数值属性排序:<=> 的替代方案
飞船运算符很方便,但如果您使用的是旧版PHP(低于7.0),则没有它。这时需要手动编写比较逻辑: