0

0

php语言怎样实现数组的排序与去重功能 php语言数组排序去重的详细方法教程

雪夜

雪夜

发布时间:2025-08-01 17:47:01

|

1082人浏览过

|

来源于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语言在处理数组的排序与去重方面,提供了相当丰富且灵活的内置函数,这使得我们能够高效地管理和操作数据。核心来看,无论是需要按值、按键,还是按自定义规则排序,亦或是移除重复元素,PHP都有成熟的解决方案。

php语言怎样实现数组的排序与去重功能 php语言数组排序去重的详细方法教程

解决方案

PHP提供了多种函数来满足数组排序和去重的需求。对于排序,最常用的是

sort()
rsort()
asort()
arsort()
ksort()
krsort()
,以及处理复杂场景的
usort()
uasort()
uksort()
array_multisort()
。去重方面,
array_unique()
是首选,但对于更复杂的数据类型,可能需要一些变通的方法。

数组排序:

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

php语言怎样实现数组的排序与去重功能 php语言数组排序去重的详细方法教程
  • 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数组排序方法,说实话,一开始确实有点让人眼花缭乱。但核心原则是:你关心的是“值”还是“键”?排序后是否需要保持原来的键?以及你的排序逻辑是不是非常个性化?

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
)并返回一个未去重的数组,或者行为不符合预期。

AI Web Designer
AI Web Designer

AI网页设计师,快速生成个性化的网站设计

下载

那么,高效技巧呢? 对于大多数包含标量(数字、字符串)的数组,

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()
出来的实例。这种情况下,你需要自己定义“相等”的逻辑。一种常见的做法是:

  1. 定义对象的唯一标识方法:在对象内部实现一个方法,比如
    getUniqueKey()
    ,它返回一个能唯一代表该对象内容的字符串(比如
    md5(serialize($this))
    ,或者拼接关键属性)。
  2. 遍历去重:创建一个新的空数组,然后遍历原始数组。对于每个对象,调用
    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中的复杂数组操作。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

410

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

638

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

362

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

263

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

631

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

564

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

671

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

618

2023.09.22

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 13.5万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 1.0万人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号