使用usort对数据进行重新排序

对数组进行排序

  • usort 函数
    • 这部分是用来对数组进行排序的“骨架”;
      1
      2
      3
      usort($items, function($a, $b) { 
      // ... 这里是排序的逻辑 ...
      });
    • 版本要求:PHP 4+。
    • 作用:它接收一个数组 ($items) 和一个自定义的比较函数,然后根据这个函数的返回值来给数组排序。
  • <=> 太空船运算符
    • 这部分是写在比较函数内部的“灵魂”,也就是排序的具体逻辑;
      1
      return $a['distance'] <=> $b['distance'];
    • 版本要求:PHP 7.0+。
    • 作用:这是一个组合比较符。它可以一次性比较两个值:
      • 如果 $a[‘distance’] 小于 $b[‘distance’],返回 -1。
      • 如果 $a[‘distance’] 等于 $b[‘distance’],返回 0。
      • 如果 $a[‘distance’] 大于 $b[‘distance’],返回 1。
    • 意义:在 PHP 7 之前,你需要用 if-else 写好几行才能实现这个功能 。太空船运算符让代码变得非常简洁。
    • 💡 核心结论
    • 所以,这段代码能正常运行的最低要求是 PHP 7.0。
    • 如果你的服务器 PHP 版本低于 7.0(比如还是 PHP 5.6 或更早),运行这段代码就会报错,因为程序不认识 <=> 这个“外星符号”。
    • ✍️ 如果想兼容低版本 PHP
    • 如果你需要在 PHP 7 以下的环境中运行,可以把 <=> 运算符改写成传统的 if-else 逻辑,效果是完全一样的。你的代码可以这样修改:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
          usort($items, function($a, $b) {
      // 处理距离为0的情况
      if ($a['distance'] == 0 && $b['distance'] != 0) {
      return 1;
      }
      if ($b['distance'] == 0 && $a['distance'] != 0) {
      return -1;
      }

      // 改用传统的 if-else 来实现升序比较,替代 $a['distance'] <=> $b['distance']
      if ($a['distance'] < $b['distance']) {
      return -1; // a 小于 b,a 排在前面
      } elseif ($a['distance'] > $b['distance']) {
      return 1; // a 大于 b,a 排在后面
      } else {
      return 0; // 相等,位置不变
      }
      });
      • 这样修改后,代码就兼容 PHP 4 及以上的所有版本了,虽然看起来会稍微长一点点,但逻辑是完全一样的。

使用案例讲解

  • $a 和 $b 是 比较函数中的两个参数,代表被比较的两个数组元素。让我用一个简单的类比来解释:
    打个比方
  • 想象你是一个体育老师,要给学生按身高排队:
  • 你一次只能比较两个学生
  • $a 就是第一个学生
  • $b 就是第二个学生
  • 你决定谁应该站在前面,谁应该站在后面
    具体例子
  • 假设有这样的数据:
    1
    2
    3
    4
    5
        $items = [
    ['name' => '张三', 'distance' => 5],
    ['name' => '李四', 'distance' => 2],
    ['name' => '王五', 'distance' => 8],
    ];
  • 当 usort 开始排序时,它会多次调用你的比较函数,每次传入不同的 $a 和 $b:
    第1次比较:
    1
    2
    $a = ['name' => '李四', 'distance' => 2]  // 数组中的第二个元素
    $b = ['name' => '张三', 'distance' => 5] // 数组中的第一个元素
    第2次比较:
    1
    2
    $a = ['name' => '王五', 'distance' => 8]  // 数组中的第三个元素
    $b = ['name' => '李四', 'distance' => 2] // 数组中的第二个元素
    第3次比较:
    1
    2
    $a = ['name' => '张三', 'distance' => 5]  // 数组中的第一个元素
    $b = ['name' => '王五', 'distance' => 8] // 数组中的第三个元素

函数的工作过程

1
2
3
4
5
6
7
8
9
10
11
12
13
   usort($items, function($a, $b) {
// $a 和 $b 是当前正在比较的两个工人
// 你可以通过 $a['distance'] 获取第一个工人的距离
// 你可以通过 $b['distance'] 获取第二个工人的距离

if ($a['distance'] == 0 && $b['distance'] != 0) {
return 1; // 告诉排序函数:$a 应该排在 $b 后面
}

// 返回负数:$a 排在 $b 前面
// 返回正数:$a 排在 $b 后面
// 返回0:位置不变
});

简单记忆

  • $a 和 $b 只是临时变量名,可以换成任何名字
  • 它们代表数组中的两个元素
  • 通过比较它们来决定谁先谁后
  • 排序算法会自动用不同的元素对来调用这个函数,直到整个数组有序
  • 就像你用手拿着两个学生比较身高一样,$a 和 $b 就是你手里正在比较的两个学生。