讲师中心 微信公众号
AI工具推荐 视频效率加速

PHP usort 自定义排序:将未匹配项高效置于数组末尾的策略

夏萱君_7915

夏萱君_7915

发布时间:2025-11-26 13:34:02

|

607人浏览过

|

来源于php中文网

原创

PHP usort 自定义排序:将未匹配项高效置于数组末尾的策略

本文详细探讨了如何使用 php 的 `usort` 函数,在依据一个预设的参考数组对多维数组进行自定义排序时,正确处理那些未包含在参考数组中的元素。通过分析原始代码的不足,文章提出了一种健壮的解决方案,即为未匹配项分配一个极大的排序权重(如 `php_int_max`),从而确保它们被统一放置在排序结果的末尾,并提供了详细的代码示例和注意事项。

理解 usort 与自定义排序

在 PHP 中,usort() 函数允许开发者使用自定义的比较函数对数组进行排序。这个比较函数(或称为回调函数)接收两个参数(通常是数组中的两个元素),并根据它们之间所需的相对顺序返回一个整数:

  • 如果第一个参数应排在第二个参数之前,返回负数(例如 -1)。
  • 如果第一个参数应排在第二个参数之后,返回正数(例如 1)。
  • 如果两个参数的顺序无关紧要(或被认为是相等),返回 0。

当我们需要根据一个预定义的顺序(例如一个字符串数组)来对另一个复杂数组进行排序时,usort() 是一个非常强大的工具。然而,一个常见的挑战是,当被排序的数组中包含一些元素,而这些元素并未出现在我们预定义的参考顺序中时,如何正确处理它们。通常,我们希望这些未匹配的元素被统一放置在排序结果的末尾。

原始问题分析

假设我们有一个多维数组 $itemsToSort,需要根据另一个参考数组 $sortOrder 对其进行排序。$itemsToSort 中的每个子项的第一个元素($item[0])将用于与 $sortOrder 进行匹配。目标是让 $sortOrder 中定义的元素按其在 $sortOrder 中的顺序排列,而未在 $sortOrder 中定义的元素则被放置到数组的末尾。

一个常见的错误实现方式可能如下:

立即学习“PHP免费学习笔记(深入)”;

btpanel phpsite 宝塔面板PHP网站
btpanel phpsite 宝塔面板PHP网站

宝塔面板 PHP 网站管理:站点创建、删除、启停、PHP 版本切换、域名管理、SSL证书管理、伪静态管理、数据库管理

下载
usort($itemsToSort, function($a, $b) use ($sortOrder){
   $valA = array_search($a[0], $sortOrder);
   $valB = array_search($b[0], $sortOrder);

   if ($valA === false) // 如果 A 未找到
      return -1; // 尝试将 A 放在 B 之前
   if ($valB === false) // 如果 B 未找到(此时 A 必然已找到)
      return 0; // 认为 A 和 B 顺序不变

   // 如果 A 和 B 都找到,则按其在 $sortOrder 中的索引比较
   if ($valA > $valB)
      return 1;
   if ($valA < $valB)
      return -1;
   return 0;
});

上述代码存在逻辑缺陷:

  1. if ($valA === false) return -1;:如果 $a[0] 未在 $sortOrder 中找到,此语句会返回 -1,这意味着 $a 会被排在 $b 之前。这与“将未匹配项置于末尾”的目标相悖,因为一个未匹配项不应该排在一个已匹配项之前。
  2. if ($valB === false) return 0;:此语句仅在 $valA !== false(即 $a 已找到)的情况下执行。如果此时 $valB === false(即 $b 未找到),返回 0 意味着 $a 和 $b 的相对顺序不变。然而,正确的逻辑应该是将已找到的 $a 排在未找到的 $b 之前,即返回 -1。

这些逻辑错误导致当参考数组中只指定了少量值时,排序结果无法达到预期。

解决方案:为未匹配项分配最大权重

要解决这个问题,我们可以为那些未在 $sortOrder 中找到的元素分配一个“虚拟”的、极大的排序权重。这样,在比较时,这些具有极大权重的元素自然会排在所有具有正常(较小)权重的元素之后。PHP 提供了一个常量 PHP_INT_MAX,它代表了 PHP 能处理的最大整数值,非常适合作为这种“极大权重”的代表。

示例代码

以下是使用 PHP_INT_MAX 策略的改进 usort 回调函数:

<?php

// 待排序的多维数组
$itemsToSort = [
    ['itemC', 'dataC'],
    ['itemA', 'dataA'],
    ['itemX', 'dataX'], // 未在 $sortOrder 中
    ['itemB', 'dataB'],
    ['itemY', 'dataY'], // 未在 $sortOrder 中
    ['itemD', 'dataD'],
    ['itemA', 'dataA_duplicate'], // 重复项
];

// 定义排序顺序的参考数组
$sortOrder = ['itemA', 'itemB', 'itemC'];

echo "原始数组:\n";
print_r($itemsToSort);

usort($itemsToSort, function($a, $b) use ($sortOrder){
    // 获取 $a[0] 在 $sortOrder 中的索引,如果未找到则为 false
    $rankA = array_search($a[0], $sortOrder);
    // 获取 $b[0] 在 $sortOrder 中的索引,如果未找到则为 false
    $rankB = array_search($b[0], $sortOrder);

    // 如果未找到,将其排序权重设置为 PHP_INT_MAX,确保其排在所有已找到项之后
    $rankA = ($rankA === false) ? PHP_INT_MAX : $rankA;
    $rankB = ($rankB === false) ? PHP_INT_MAX : $rankB;

    // 比较两个元素的最终排序权重
    if ($rankA > $rankB) {
        return 1; // A 排在 B 之后
    }
    if ($rankA < $rankB) {
        return -1; // A 排在 B 之前
    }
    return 0; // 权重相等,保持原有相对顺序(或认为相等)
});

echo "\n排序后的数组:\n";
print_r($itemsToSort);

?>

代码解析

  1. array_search($a[0], $sortOrder): 此函数用于查找 $a[0] 在 $sortOrder 数组中的键名(即索引)。如果找到,它会返回相应的整数索引;如果未找到,则返回布尔值 false。
  2. ($rankA === false) ? PHP_INT_MAX : $rankA;: 这是一个三元运算符。它的作用是:
    • 如果 $rankA(或 $rankB)为 false,表示对应的元素未在 $sortOrder 中找到,那么将其排序权重设置为 PHP_INT_MAX。
    • 如果 $rankA 不为 false,表示元素已找到,则保留其在 $sortOrder 中的实际索引作为排序权重。
  3. 最终比较: 经过上述处理后,所有的元素都有了一个数值型的排序权重。我们只需直接比较 $rankA 和 $rankB 即可。
    • if ($rankA > $rankB) return 1;:如果 A 的权重更大(索引值更大或为 PHP_INT_MAX),则 A 排在 B 之后。
    • if ($rankA
    • return 0;:如果权重相等,则保持它们的相对顺序。这适用于两种情况:一是两个元素都在 $sortOrder 中且具有相同的索引(通常不会发生,除非 $sortOrder 有重复值且 array_search 找到的是第一个);二是两个元素都未在 $sortOrder 中找到,都分配了 PHP_INT_MAX。

运行结果

原始数组:
Array
(
    [0] => Array
        (
            [0] => itemC
            [1] => dataC
        )

    [1] => Array
        (
            [0] => itemA
            [1] => dataA
        )

    [2] => Array
        (
            [0] => itemX
            [1] => dataX
        )

    [3] => Array
        (
            [0] => itemB
            [1] => dataB
        )

    [4] => Array
        (
            [0] => itemY
            [1] => dataY
        )

    [5] => Array
        (
            [0] => itemD
            [1] => dataD
        )

    [6] => Array
        (
            [0] => itemA
            [1] => dataA_duplicate
        )

)

排序后的数组:
Array
(
    [0] => Array
        (
            [0] => itemA
            [1] => dataA
        )

    [1] => Array
        (
            [0] => itemA
            [1] => dataA_duplicate
        )

    [2] => Array
        (
            [0] => itemB
            [1] => dataB
        )

    [3] => Array
        (
            [0] => itemC
            [1] => dataC
        )

    [4] => Array
        (
            [0] => itemX
            [1] => dataX
        )

    [5] => Array
        (
            [0] => itemY
            [1] => dataY
        )

    [6] => Array
        (
            [0] => itemD
            [1] => dataD
        )

)

从结果可以看出,itemA、itemB、itemC 按照 $sortOrder 的顺序排列,

相关文章

PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

PixTV
PixTV Hot

PixTV是一款面向AIGC内容创作的AI视频生成工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

创客贴AI

创客贴AI是一款AI图像与设计工具,AI辅助的智能在线设计工具。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6184

2023.10.24

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6184

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3144

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

1832

2025.10.17

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

1832

2025.10.17

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1798

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2864

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

6184

2023.10.24

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
墨刀帮助中心
墨刀帮助中心

共0课时 | 0人学习

MyEclipse学习中心
MyEclipse学习中心

共0课时 | 0人学习

Apache Subversion 官方手册
Apache Subversion 官方手册

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn