PHP数组排序去重全攻略
本文深入解析了PHP数组排序与去重的多种方法,旨在帮助开发者高效处理各类数据操作需求。针对简单数组,可选用`sort()`、`rsort()`进行升序或降序排列;关联数组则推荐`asort()`、`arsort()`、`ksort()`、`krsort()`以保留键值关系。对于复杂排序逻辑,`usort()`、`uasort()`、`uksort()`结合自定义比较函数提供强大支持。多维数组或多数组同步排序,`array_multisort()`是理想之选。去重方面,`array_unique()`适用于标量值,对象去重可借助`SplObjectStorage`或手动创建唯一键。掌握这些技巧,能有效提升PHP数组处理能力,优化代码性能。
PHP提供了丰富的内置函数处理数组排序与去重,核心在于根据数据类型和需求选择合适方法。1. 对于简单数组排序,若不需保留键,使用sort()升序或rsort()降序;2. 关联数组按值排序且保留键用asort()或arsort();3. 按键排序使用ksort()或krsort();4. 复杂排序逻辑使用usort()、uasort()或uksort()配合自定义比较函数;5. 多维数组或多个数组同步排序使用array_multisort();6. 去重首选array_unique(),但仅适用于标量值;7. 对象去重若基于实例唯一性可用SplObjectStorage;8. 内容相同但实例不同的对象或复杂结构去重,可通过唯一键(如序列化或属性组合)手动去重。这些方法结合使用可高效处理各类数组操作需求。
PHP语言在处理数组的排序与去重方面,提供了相当丰富且灵活的内置函数,这使得我们能够高效地管理和操作数据。核心来看,无论是需要按值、按键,还是按自定义规则排序,亦或是移除重复元素,PHP都有成熟的解决方案。

解决方案
PHP提供了多种函数来满足数组排序和去重的需求。对于排序,最常用的是sort()
、rsort()
、asort()
、arsort()
、ksort()
、krsort()
,以及处理复杂场景的usort()
、uasort()
、uksort()
和array_multisort()
。去重方面,array_unique()
是首选,但对于更复杂的数据类型,可能需要一些变通的方法。
数组排序:

sort(array &$array, int $flags = SORT_REGULAR)
: 对数组进行升序排序,并重新建立索引(数字键会被重置为0, 1, 2...)。$numbers = [3, 1, 4, 1, 5, 9]; sort($numbers); // $numbers 现在是 [1, 1, 3, 4, 5, 9]
rsort(array &$array, int $flags = SORT_REGULAR)
: 与sort()
相反,进行降序排序,同样重新建立索引。asort(array &$array, int $flags = SORT_REGULAR)
: 对关联数组按值进行升序排序,并保持键值关联。$grades = ['Math' => 90, 'Physics' => 85, 'English' => 92]; asort($grades); // $grades 现在是 ['Physics' => 85, 'Math' => 90, 'English' => 92]
arsort(array &$array, int $flags = SORT_REGULAR)
: 与asort()
相反,按值降序排序并保持键值关联。ksort(array &$array, int $flags = SORT_REGULAR)
: 对关联数组按键进行升序排序。$data = ['c' => 3, 'a' => 1, 'b' => 2]; ksort($data); // $data 现在是 ['a' => 1, 'b' => 2, 'c' => 3]
krsort(array &$array, int $flags = SORT_REGULAR)
: 与ksort()
相反,按键降序排序。usort(array &$array, callable $callback)
: 使用用户自定义的比较函数对数组按值进行排序。这在需要复杂排序逻辑时非常有用,比如对对象数组按某个属性排序。它会重新建立索引。$users = [ ['name' => 'Alice', 'age' => 30], ['name' => 'Bob', 'age' => 25], ['name' => 'Charlie', 'age' => 30] ]; usort($users, function($a, $b) { if ($a['age'] == $b['age']) { return $a['name'] <=> $b['name']; // 如果年龄相同,按名字排序 } return $a['age'] <=> $b['age']; // 否则按年龄排序 }); // $users 现在按年龄升序,年龄相同则按名字升序
uasort()
/uksort()
: 分别是usort()
的关联数组版本(保持键值关联)和按键自定义排序版本。array_multisort()
: 用于对多个数组或多维数组的特定列进行排序。
数组去重:
array_unique(array $array, int $flags = SORT_REGULAR)
: 移除数组中的重复值。默认情况下,它会保留第一次出现的键值对,并移除后续重复的。$colors = ['red', 'green', 'blue', 'red', 'yellow', 'green']; $uniqueColors = array_unique($colors); // $uniqueColors 现在是 ['red', 'green', 'blue', 'yellow']
PHP数组排序,我究竟该选哪种方法?
选择正确的PHP数组排序方法,说实话,一开始确实有点让人眼花缭乱。但核心原则是:你关心的是“值”还是“键”?排序后是否需要保持原来的键?以及你的排序逻辑是不是非常个性化?

如果你的数组是简单的数字或字符串列表,且你不在乎原来的索引,sort()
或rsort()
无疑是最直接的选择。它们效率高,用起来也省心。比如,你有一堆考试分数,只想知道从低到高或从高到低排列,那它们就够了。
但如果你的数组是关联数组,比如用户ID对应用户名的那种,而你希望按用户名排序,同时又不想打乱ID和用户名的对应关系,那么asort()
(升序)或arsort()
(降序)就是你的救星。它们会保持键值对的“粘性”,只调整它们在数组中的位置。同理,如果你想按键名排序(比如按字母顺序排列配置项),ksort()
和krsort()
就派上用场了。
而当你的排序需求变得复杂,比如你有一个对象数组,每个对象都有名字、年龄、分数等属性,你想先按年龄排序,年龄相同再按分数排序,甚至分数相同再按名字排序……这种时候,内置的简单排序函数就力不从心了。这时,usort()
(如果需要重置索引)或uasort()
(如果需要保持键值关联)就成了不二之选。它们允许你传入一个自定义的比较函数,完全掌控排序逻辑。这个函数会接收两个元素作为参数,你只需要告诉PHP这两个元素谁应该排在前面(返回负数),谁排在后面(返回正数),或者它们是相等的(返回0)。这种灵活性是其他函数无法比拟的,虽然写起来多几行代码,但能解决绝大多数复杂排序问题。
// 假设有一个商品列表,需要先按价格降序,价格相同则按库存升序 $products = [ ['name' => 'Laptop', 'price' => 1200, 'stock' => 50], ['name' => 'Mouse', 'price' => 25, 'stock' => 200], ['name' => 'Keyboard', 'price' => 1200, 'stock' => 30], ['name' => 'Monitor', 'price' => 300, 'stock' => 80] ]; uasort($products, function($a, $b) { if ($a['price'] == $b['price']) { return $a['stock'] <=> $b['stock']; // 价格相同,按库存升序 } return $b['price'] <=> $a['price']; // 否则按价格降序 }); /* $products 现在是: [ ['name' => 'Keyboard', 'price' => 1200, 'stock' => 30], ['name' => 'Laptop', 'price' => 1200, 'stock' => 50], ['name' => 'Monitor', 'price' => 300, 'stock' => 80], ['name' => 'Mouse', 'price' => 25, 'stock' => 200] ] */
这种自定义排序的能力,真的让PHP处理复杂数据变得游刃有余。
PHP数组去重,有哪些常见陷阱和高效技巧?
说起PHP数组去重,array_unique()
无疑是第一个想到的,它简单直接,大多数时候也表现得很好。但就像所有看似简单的工具一样,它也有自己的“脾气”和“盲区”,尤其是在处理一些非标量数据类型时。
一个常见的陷阱是类型转换。array_unique()
在比较元素时,默认会进行松散比较(==
),这意味着它可能把0
和"0"
、null
和false
、甚至"1"
和1
视为相同的值。这在某些场景下可能是你想要的,但如果你的数据对类型非常敏感,这就会导致意想不到的去重结果。例如:
$data = [0, "0", false, null, 1, "1"]; $uniqueData = array_unique($data); // $uniqueData 可能是 [0, 1] 或类似的,具体取决于PHP版本和内部实现,但会把0, "0", false, null 视为相同
如果你需要严格的类型比较,array_unique
本身无法直接做到,你可能需要手动遍历或者在去重前进行类型规范化。
另一个大陷阱是对象和多维数组。array_unique()
对它们是“无能为力”的。它无法直接比较两个对象是否“相等”(除非对象实现了特定的比较魔术方法,但通常不是你想要的深层比较),也无法理解两个嵌套数组是否内容相同。当你把一个包含对象或多维数组的数组传给它时,它会发出警告(E_NOTICE
)并返回一个未去重的数组,或者行为不符合预期。
那么,高效技巧呢?
对于大多数包含标量(数字、字符串)的数组,array_unique()
是绝对的首选,因为它底层是C语言实现,效率非常高。你几乎不需要担心它的性能问题,除非你的数组有数百万甚至上千万个元素。
当涉及到对象去重时,就没有那么直接了。如果你想去重的是同一个对象的不同引用,PHP的SplObjectStorage
类是神器。它专门用来存储对象并能快速判断对象是否存在,基于的是对象的唯一标识(而不是值)。
$obj1 = new stdClass(); $obj1->id = 1; $obj2 = new stdClass(); $obj2->id = 2; $obj3 = new stdClass(); $obj3->id = 1; // 内容相同,但这是不同的对象实例 $objects = [$obj1, $obj2, $obj3, $obj1]; // obj1出现了两次 $storage = new SplObjectStorage(); foreach ($objects as $obj) { $storage->attach($obj); } $uniqueObjects = iterator_to_array($storage); // $uniqueObjects 包含 $obj1, $obj2, $obj3 三个不同的对象实例,即使 $obj1 引用被重复添加,SplObjectStorage 也只存储一次
但如果你想去重的是“内容相同”但“实例不同”的对象,那就需要自定义逻辑了。通常的做法是给每个对象定义一个唯一的标识符(比如一个ID属性),然后把这个ID作为键存到一个临时数组里,或者在usort
或uasort
中自定义比较逻辑。
对于多维数组去重,一种常见的“黑科技”是序列化-去重-反序列化。你可以将每个子数组序列化成字符串,然后对这些字符串进行array_unique()
,最后再反序列化回来。这种方法简单粗暴,但要注意序列化的开销和一些序列化可能带来的问题(比如对象属性的可见性)。
$nestedArrays = [ ['a' => 1, 'b' => 2], ['c' => 3, 'd' => 4], ['a' => 1, 'b' => 2], // 重复项 ['e' => 5, 'f' => 6] ]; $serializedArrays = array_map('serialize', $nestedArrays); $uniqueSerializedArrays = array_unique($serializedArrays); $uniqueNestedArrays = array_map('unserialize', $uniqueSerializedArrays); /* $uniqueNestedArrays 现在是: [ ['a' => 1, 'b' => 2], ['c' => 3, 'd' => 4], ['e' => 5, 'f' => 6] ] */
这方法虽然有效,但序列化和反序列化本身是有性能成本的,对于非常大的数组,需要权衡。
如何处理包含复杂数据类型(如对象或多维数组)的排序和去重?
当数组里装的不再是简单的数字或字符串,而是对象或者嵌套的数组时,排序和去重就变得有意思了,因为PHP内置的那些通用函数,很多时候就不那么“智能”了。
复杂数据类型的排序:
对于包含对象的数组,最常见也最强大的工具就是usort()
或uasort()
。你必须提供一个自定义的比较函数,告诉PHP如何判断两个对象谁大谁小。这个比较逻辑完全取决于你的业务需求。比如,你可能想按对象的某个属性值排序,或者根据多个属性的组合来排序。
class Product { public $name; public $price; public $stock; public function __construct($name, $price, $stock) { $this->name = $name; $this->price = $price; $this->stock = $stock; } } $products = [ new Product('Laptop', 1200, 50), new Product('Mouse', 25, 200), new Product('Keyboard', 1200, 30), new Product('Monitor', 300, 80) ]; // 需求:先按价格降序,价格相同则按库存升序 usort($products, function(Product $a, Product $b) { if ($a->price == $b->price) { return $a->stock <=> $b->stock; // 价格相同,按库存升序 } return $b->price <=> $a->price; // 否则按价格降序 }); // 此时 $products 数组中的对象已经按你定义的规则排序了
对于多维数组的排序,usort()
同样适用,你只需在比较函数中访问子数组的对应键即可。此外,PHP还有一个array_multisort()
函数,它能同时对多个数组进行排序,或者对多维数组的特定“列”进行排序。这在处理类似数据库查询结果的场景时特别有用。
$data = [ ['name' => 'Alice', 'age' => 30, 'score' => 85], ['name' => 'Bob', 'age' => 25, 'score' => 90], ['name' => 'Charlie', 'age' => 30, 'score' => 92], ]; // 提取出需要排序的“列” $ages = array_column($data, 'age'); $scores = array_column($data, 'score'); // 按照年龄升序,年龄相同则按分数降序 array_multisort($ages, SORT_ASC, SORT_NUMERIC, $scores, SORT_DESC, SORT_NUMERIC, $data); // $data 现在按照年龄和分数排序了
array_multisort()
的用法稍微复杂一点,但它在处理表格数据或多个相关数组的同步排序时非常高效。
复杂数据类型的去重:
这才是真正考验你对数据结构理解的地方。array_unique()
对对象和多维数组是无效的,因为它无法判断它们的“相等性”。
对于对象去重,如果你的“去重”指的是移除完全相同的对象实例(即同一个对象在内存中的不同引用),那么前面提到的SplObjectStorage
是最佳选择。它基于对象在内存中的唯一标识符来判断是否重复。
然而,更常见的情况是,你希望移除的是“内容相同”但可能是不同实例的对象。例如,你有两个Product
对象,它们的名字、价格、库存都一样,但它们是不同的new Product()
出来的实例。这种情况下,你需要自己定义“相等”的逻辑。一种常见的做法是:
- 定义对象的唯一标识方法:在对象内部实现一个方法,比如
getUniqueKey()
,它返回一个能唯一代表该对象内容的字符串(比如md5(serialize($this))
,或者拼接关键属性)。 - 遍历去重:创建一个新的空数组,然后遍历原始数组。对于每个对象,调用
getUniqueKey()
获取其唯一键,然后用这个键作为临时数组的键,将对象存入。由于数组键的唯一性,重复的对象就会被覆盖,从而达到去重目的。
class Product { public $name; public $price; public $stock; public function __construct($name, $price, $stock) { $this->name = $name; $this->price = $price; $this->stock = $stock; } // 定义一个方法来获取对象的唯一标识 public function getUniqueKey(): string { return md5($this->name . '|' . $this->price . '|' . $this->stock); } } $products = [ new Product('Laptop', 1200, 50), new Product('Mouse', 25, 200), new Product('Laptop', 1200, 50), // 内容重复 new Product('Monitor', 300, 80) ]; $uniqueProducts = []; $seenKeys = []; foreach ($products as $product) { $key = $product->getUniqueKey(); if (!isset($seenKeys[$key])) { $uniqueProducts[] = $product; $seenKeys[$key] = true; } } // $uniqueProducts 现在只包含内容唯一的Product对象
这种方法对于多维数组去重也同样适用,只需将子数组序列化成字符串作为唯一键即可。但要记住,序列化和反序列化操作会带来额外的性能开销,对于极大的数据集,需要仔细考虑。在实际开发中,理解这些方法的原理和适用场景,能帮助你更灵活、高效地处理PHP中的复杂数组操作。
好了,本文到此结束,带大家了解了《PHP数组排序去重全攻略》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多文章知识!

- 上一篇
- Java枚举定义常量方法详解

- 下一篇
- CSS平滑滚动锚点实现方法
-
- 文章 · php教程 | 1分钟前 |
- PHP7到PHP8升级5大实用技巧
- 324浏览 收藏
-
- 文章 · php教程 | 4分钟前 | docker PHP扩展 Dockerfile 多阶段构建 docker-php-ext-install
- Docker添加PHP扩展教程详解
- 205浏览 收藏
-
- 文章 · php教程 | 10分钟前 |
- PHPCMS清理缓存与临时文件教程
- 374浏览 收藏
-
- 文章 · php教程 | 19分钟前 |
- Laravel8.env数组配置技巧
- 252浏览 收藏
-
- 文章 · php教程 | 21分钟前 |
- PHPMyAdmin日志配置教程
- 430浏览 收藏
-
- 文章 · php教程 | 31分钟前 |
- Docker下WordPress升级PHP的正确方法
- 215浏览 收藏
-
- 文章 · php教程 | 37分钟前 |
- ContactForm7获取RefererURL方法
- 425浏览 收藏
-
- 文章 · php教程 | 40分钟前 |
- Laravel多应用队列共享与任务处理技巧
- 219浏览 收藏
-
- 文章 · php教程 | 1小时前 |
- PHP二叉树递归遍历技巧与优化方法
- 146浏览 收藏
-
- 文章 · php教程 | 1小时前 |
- VueLaravelBootstrap表单验证技巧
- 310浏览 收藏
-
- 文章 · php教程 | 1小时前 | 文件上传 php.ini fileinfo扩展 文件类型验证 魔术字节
- PHP启用Fileinfo扩展的正确方法
- 274浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 113次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 109次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 126次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 118次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 122次使用
-
- PHP技术的高薪回报与发展前景
- 2023-10-08 501浏览
-
- 基于 PHP 的商场优惠券系统开发中的常见问题解决方案
- 2023-10-05 501浏览
-
- 如何使用PHP开发简单的在线支付功能
- 2023-09-27 501浏览
-
- PHP消息队列开发指南:实现分布式缓存刷新器
- 2023-09-30 501浏览
-
- 如何在PHP微服务中实现分布式任务分配和调度
- 2023-10-04 501浏览