php数组合并的二种方法
前言「把两个数组合成一个」在 PHP 里有两套写法array_merge()函数和数组联合运算符。很多文章把它们写成「差不多随便挑一个」这是本文要纠正的第一个误解——它们处理键的规则完全相反array_merge()是「后面的覆盖前面的、数字键全部重新编号」是「左边的优先、一个键都不动」。选错了症状往往不是报错而是数据被悄悄覆盖或下标莫名其妙地变了非常难查。第二个常见误解是「合并就是array_merge拆分就是array_slice」。PHP 在合并与拆分这件事上其实给了好几把不同的工具各自对键的处理规则都不一样array_merge_recursive()会在字符串键冲突时递归合并array_replace()是「后者覆盖前者但保留键」array_slice()默认重置数字键array_splice()会直接改掉原数组。本文先讲清两种合并方法的规则差异再给出三种典型场景该怎么选最后把拆分方向的array_chunk()、array_slice()、array_splice()、array_combine()一次讲完。文中所有示例都可以直接复制运行基准版本是 PHP 8.0 及以上涉及版本差异的地方会单独标注。一、array_merge()字符串键后者覆盖数字键重新编号array_merge(array ...$arrays): array的规则只有两条但它们组合起来的效果很反直觉字符串键冲突时后面的值覆盖前面的值位置不变值被换掉。数字键不参与覆盖一律按顺序追加并从 0 开始重新编号。?php // 适用于 PHP 7.4declare(strict_types1);$a [name 张三, age 30, 0 a, 1 b];$b [name 李四, city 北京, 0 c];print_r(array_merge($a, $b));// Array// (// [name] 李四 - 字符串键被 $b 覆盖// [age] 30// [0] a - $a 的数字键从 0 重新编号// [1] b// [city] 北京// [2] c - $b 的数字键继续往下编号// )print_r($a $b);// Array// (// [name] 张三 - 字符串键保留 $a 的// [age] 30// [0] a - 数字键也保留 $a 的// [1] b// [city] 北京 - 只在 $a 里不存在的键才会补进来// )注意上面那两段输出里最容易被忽略的一点array_merge()里$b的0 c并没有覆盖$a的0 a它变成了2 c。这就是「数字键重新编号」的实际含义——如果你用数字键当业务主键订单号、用户 ID 之类array_merge()会把它们全部破坏掉。这里还要注意一个陷阱数字字符串键也不例外。键0、8、100会被 PHP 当成整数键这是数组键的强制转换规则因此同样会被array_merge()重新编号。把整数塞进字符串键里并不能保住它们。array_merge_recursive()则不同当两个数组在同一个字符串键上都有值、且都是数组时它会把它们递归合并如果都是非数组的标量则把两个值合并成一个数组。数字键的处理与array_merge()一样是追加。?php // 适用于 PHP 7.4$default [db [host localhost], tags [php], mode dev];$custom [db [port 3306], tags [web], mode prod];print_r(array_merge_recursive($default, $custom));// [db] [host localhost, port 3306] - 递归合并// php,开发语言 [0 php, 1 web] - 数字键追加// [mode] [0 dev, 1 prod] - 标量冲突变成数组最后那个mode [dev, prod]就是array_merge_recursive()的坑它不会「用新的覆盖旧的」而是把两个值都留下来于是原本的字符串变成了数组下游代码拿到之后往往直接崩。二、 运算符左边优先一个键都不动是数组联合union运算符规则只有一条以左边的数组为基准把右边数组中「键在左边不存在」的元素补进来键相同的左边的赢。它和array_merge()的关键差别在数字键上不会重新编号也不会把右边同键的元素追加进去而是直接丢弃右边的同名元素。?php // 适用于 PHP 7.0$left [0 a, 1 b, k L];$right [0 c, 2 d, k R];print_r($left $right);// [0] a - 左边优先右边的 0 c 被丢弃// [1] b// [k] L - 同上// [2] d - 只在右边存在的键才补进来print_r(array_merge($left, $right));// [0] a// [1] b// [k] R - 字符串键被右边的覆盖// [2] c - 数字键被重新编号追加// [3] d把两段输出对照着看两种方法的差异一目了然场景array_merge()字符串键冲突后者覆盖前者左边保留右边丢弃数字键冲突不冲突被重新编号后全部保留左边保留右边丢弃数字键最终下标从 0 起连续重排原样不动元素顺序依次遍历每个数组按数组顺序追加左边的顺序在前右边新增的在后元素丢失不丢字符串键的值会被覆盖会丢右边同键的元素被丢弃传入非数组PHP 8.0 起抛TypeError不适用运算符只接受数组无参数调用PHP 7.4 起返回空数组此前至少要传一个参数不适用三、该用哪个三种典型场景场景一合并配置文件希望「用户配置覆盖默认配置」。这时要的是「后者覆盖前者」但又不希望数字键被重排。用array_replace()?php // 适用于 PHP 7.0$defaults [host localhost, port 3306, charset utf8mb4];$user [host db.internal, port 3307];$config array_replace($defaults, $user);print_r($config);// [host] db.internal - 后面的覆盖前面的// [port] 3307// [charset] utf8mb4 - 未冲突的键保留array_replace(array $array, array ...$replacements): array的取值规则与相反右边优先但与一样保留原有键、不重排数字键。它和$user $defaults取到的值相同差别在顺序array_replace()保持第一个数组的元素顺序则把左操作数的元素排在前面。做配置合并时顺序稳定通常更重要所以优先用array_replace()。场景二合并两个列表不关心原来的下标。例如把两组待处理 ID 拼成一个队列用array_merge()?php // 适用于 PHP 7.4$pending [101, 102, 103];$retry [102, 104]; // 注意 102 重复了$queue array_merge($pending, $retry);// [101, 102, 103, 102, 104] —— 下标连续重复值不会自动去重$unique array_values(array_unique($queue));// [101, 102, 103, 104]这里要记住array_merge()不去重。想按值去重用array_unique()想按「是不是同一个 ID」去重用键来承载语义$map[$id] true比用值更可靠。场景三合并两个以 ID 为键的映射保留 ID。这时候array_merge()会把 ID 全部重排会丢掉右边同名 ID 的新数据两个都不合适应该自己控制覆盖方向?php // 适用于 PHP 7.0/** param arrayint,string $old param arrayint,string $new */function mergeById(array $old, array $new): array{// 后者优先先放新的再用「旧数组中新增部分」补齐return $new $old;}$old [7 旧名称, 9 未变];$new [7 新名称, 11 新增];print_r(mergeById($old, $new));// [7] 新名称 - 新数据优先// [11] 新增// [9] 未变 - 左边没有的键补进来注意array_merge()在没有参数时返回空数组PHP 7.4 起才允许无参调用之前的版本至少要传一个参数。所以array_merge(...$arrays)这种展开写法在数组为空时是合法的条件是 PHP 7.4 及以上。四、拆分方向四个常用函数合并讲完把拆分方向的四个函数一次交代清楚。它们的共同问题是「键怎么处理」而这恰恰是手册里最容易看漏的部分。array_chunk(array $array, int $length, bool $preserve_keys false): array—— 按长度切块返回二维数组外层从 0 开始编号。?php // 适用于 PHP 8.0$ids range(1, 7);print_r(array_chunk($ids, 3));// [[1,2,3], [4,5,6], [7]]$assoc [a 1, b 2, c 3];print_r(array_chunk($assoc, 2, true)); // 第三参数 true保留原键// [[a 1, b 2], [c 3]]$length小于 1 时PHP 8.0 起抛ValueError更早的版本是E_WARNING并返回null。array_slice(array $array, int $offset, ?int $length null, bool $preserve_keys false): array—— 取一段不修改原数组。?php // 适用于 PHP 7.0$arr [10 a, 20 b, k c, 30 d];print_r(array_slice($arr, 1, 2));// [0] b - 整数键被重置为 0 起编号// [k] c - 字符串键始终保留print_r(array_slice($arr, 1, 2, true));// [20] b - 传 true 才保留整数键// [k] c规则可以记成一句字符串键永远保留整数键默认重置除非第四个参数传true。array_splice(array $array, int $offset, ?int $length null, mixed $replacement []): array—— 从原数组中「剪掉」一段并可选地插入新内容返回值是被剪掉的那部分。注意它接收的是引用原数组会被直接修改。?php // 适用于 PHP 7.0$input [red, green, blue, yellow];$removed array_splice($input, 1, 2, [black, maroon]);print_r($input);// [red, black, maroon, yellow] - 原数组被改掉了print_r($removed);// [green, blue] - 返回值是被删掉的部分关于键手册明确承诺的只有两条输入数组的数字键不保留替换数组的键也不保留。至于输入数组里字符串键在array_splice()之后是什么行为手册没有给出承诺不要依赖。要在关联数组上做「按位置插入」稳妥做法是先用array_keys()定位、再用array_slice()拼接而不是猜array_splice()的字符串键行为。array_combine(array $keys, array $values): array—— 把两个等长数组拼成「第一个数组的值当键、第二个数组的值当值」。?php // 适用于 PHP 8.0$fields [host, port, user];$vals [localhost, 3306, root];print_r(array_combine($fields, $vals));// [host localhost, port 3306, user root]// 两个数组长度不一致时try {array_combine($fields, [localhost]); // PHP 8.0 抛 ValueError} catch (ValueError $e) {echo 长度不一致 . $e-getMessage() . \n;}在PHP 8.0 之前长度不一致只会发一条E_WARNING并返回falsePHP 8.0 起改为抛ValueError。所以「先把返回值当false判断」的老代码在新版本上会直接中断。另外键数组里如果出现重复值后面的会覆盖前面的。常见坑点❌ 用array_merge()合并以数字 ID 为键的数组期望保留下标。✅ 数字键会被从 0 开始重新编号数字字符串键也一样此时应改用或array_replace()。❌ 用$old $new合并配置以为新的会覆盖旧的。✅是左边优先$old里已存在的键不会被$new覆盖要「后者覆盖前者」用array_replace($old, $new)。❌ 以为array_merge()对同名字符串键会「合并内容」。✅array_merge()是同名键直接覆盖会做递归合并的是array_merge_recursive()而它会把标量冲突变成数组。❌ 把null或字符串直接传给array_merge()。✅ PHP 8.0 起抛TypeError此前是E_WARNING并返回null先确认参数都是数组。❌ 给array_chunk()传$length 0却没有处理返回值。✅ 小于 1 时 PHP 8.0 起抛ValueError先自行校验长度再调用。❌ 用array_slice()取关联数组的一段发现整数键「变了」。✅ 整数键默认被重新编号需要保留就传第四个参数true字符串键无论如何都保留。❌ 为拿返回值而调用array_splice()忘了它会修改原数组。✅ 它第一个参数是按引用传递的原数组会被改写只想取片段、不动原数组就用array_slice()。❌ 用if (array_combine($k, $v) false)处理两个数组长度不等的情况。✅ PHP 8.0 起抛ValueError而不是返回false要么先count()比较要么用try/catch接住。总结需求推荐键的处理合并列表下标无所谓array_merge()字符串键后者覆盖数字键从 0 重排合并配置后者覆盖前者array_replace()键全部保留右边同键的值胜出合并映射左边优先键全部保留左边同键的元素胜出深层合并配置array_merge_recursive()字符串键递归合并数字键追加标量冲突变成数组按长度切块array_chunk()默认重排数字键第三参数为true时保留取一段但不动原数组array_slice()字符串键保留整数键默认重排剪一段并就地插入array_splice()手册只承诺数字键与替换键不保留字符串键未作承诺两数组合成键值对array_combine()长度不等时 PHP 8.0 起抛ValueError选哪种合并方式先问自己一个问题「键到底有没有业务含义」如果键只是下标用array_merge()最省事如果键是 ID、配置项名、字段名就绝对不能让它被重排或覆盖此时与array_replace()才是安全的两者的区别只在于「谁优先」和「元素顺序」。至于拆分方向记住array_slice()不改原数组、array_splice()改原数组且字符串键行为未作承诺基本就不会踩到最疼的那几个坑了。

相关新闻

信创测试中的异常场景设计与故障注入实战

信创测试中的异常场景设计与故障注入实战

1. 信创测试里的异常场景,到底在测什么1.1 从一次真实故障说起先讲个我最近遇到的案例。某个单位做信创迁移,把一套OA系统从x86Windows迁移到了麒麟V10鲲鹏920的国产化环境,迁移完成后功能测试、性能测试全部通过,系统顺利上线。结…

2026/10/10 14:45:49 阅读更多 →
人脸表情识别端到端实战:从OpenCV检测到TensorRT部署

人脸表情识别端到端实战:从OpenCV检测到TensorRT部署

简介:本资源是一份基于Python实现的人脸表情识别入门级开发实践包,面向计算机视觉初学者、后端开发人员及AI兴趣学习者,聚焦人脸68个关键点定位这一核心预处理环节,为后续表情分类与情感分析提供可靠特征基础。压缩包共2个文件&am…

2026/10/10 14:44:48 阅读更多 →
U-Net+PatchGAN图像修复实战:可落地的深度学习方案

U-Net+PatchGAN图像修复实战:可落地的深度学习方案

简介:本资源是一套基于深度学习的图像修复算法完整实现方案,面向计算机、人工智能、电子信息等专业的本科生毕设与课程设计需求,尤其适合正在开展毕业设计或项目实战练习的学习者。内容涵盖可直接运行的Python源码、配套数据集(Pl…

2026/10/10 14:44:48 阅读更多 →

最新新闻

生物分类七级体系“界门纲目科属种”通俗详解与鉴定实操指南

生物分类七级体系“界门纲目科属种”通俗详解与鉴定实操指南

生物分类等级:界门纲目科属种认识一棵树,像认识一个家族。你不需要记住家族里每个人叫什么,但你需要理解辈分怎么排、谁跟谁是什么关系、哪个支脉出了个另类。生物分类等级“界门纲目科属种”,就是给地球上所有生命排的一份家族辈…

2026/10/10 15:36:06 阅读更多 →
基于蒙特卡洛仿真的径向低压馈线WLS状态估计与单相接地分析

基于蒙特卡洛仿真的径向低压馈线WLS状态估计与单相接地分析

1. 项目综述与核心价值看到这个标题,第一反应是“又是个电网状态估计的活儿”,但细看之后发现它其实踩中了一个非常典型的工程痛点:低压配电网不像输电网那样有完善的量测装置,单相接地故障又多,想摸清线路真实运行状态…

2026/10/10 15:36:06 阅读更多 →
文本标注工具REA:轻量级中文NER与关系抽取实践

文本标注工具REA:轻量级中文NER与关系抽取实践

我无法基于当前输入生成符合要求的博文。原因如下:输入中仅提供了项目标题"rea",未提供任何有效上下文:无【项目正文】(原始描述为空)无【关键词】列表(显示为“相关热搜词:最新网络热…

2026/10/10 15:36:06 阅读更多 →
嵌入式学习路线:从零基础到独立项目的完整指南

嵌入式学习路线:从零基础到独立项目的完整指南

很多想认真学嵌入式的人,买回开发板之后做的第一件事,是把商家给的例程编译下载,看到LED闪烁、串口打印出“Hello World”,然后……就没有然后了。我也经历过这个阶段,甚至整整卡了两个月,每天都在“下一个…

2026/10/10 15:36:06 阅读更多 →
5.5k star 却“无共振“:scriptc 在中文社区为什么热而不爆?差的一口气在哪?

5.5k star 却“无共振“:scriptc 在中文社区为什么热而不爆?差的一口气在哪?

5.5k star 却"无共振":scriptc 在中文社区为什么热而不爆?差的一口气在哪? 【免费下载链接】scriptc TypeScript-to-Native Compiler 项目地址: https://gitcode.com/GitHub_Trending/sc/scriptc 一个头顶 Vercel Labs 光环…

2026/10/10 15:36:06 阅读更多 →
从脚本到全栈交付:VibeCoding任务拆解与上下文管理实战复盘

从脚本到全栈交付:VibeCoding任务拆解与上下文管理实战复盘

今天把项目推上线的那一刻,我确实挺开心的。这个项目从需求、原型到前后端代码,绝大部分是靠VibeCoding的方式完成的——我用自然语言描述意图,AI负责生成代码,我来做架构、拆解和验收。这是我从“用AI搞点小脚本”真正转到“用AI…

2026/10/10 15:35:05 阅读更多 →

日新闻

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

卫星轨道分类全解析:从LEO到GEO的选型逻辑与工程实践

1. 从“卫星轨道分类”这个标题说起:为什么值得花时间搞懂第一次接触“卫星轨道分类”这个概念,很多人会觉得它离自己很远——不就是天上的星星怎么转吗?但如果你正在做航天任务规划、遥感数据接收、星座设计,甚至只是准备一场航天…

2026/10/10 0:00:39 阅读更多 →
Spring AOP 核心原理与实战:从概念到日志切面落地

Spring AOP 核心原理与实战:从概念到日志切面落地

1. 从一个真实痛点说起:为什么你的代码里到处都是重复逻辑刚入行那会儿,我写过一个用户管理模块,注册、登录、改密码、注销四个接口。每个接口里都塞了几乎一样的日志打印、参数校验、事务开启和提交。当时觉得没什么,能跑就行。直…

2026/10/10 0:00:40 阅读更多 →
Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

Python招聘数据采集与分析可视化:从采集清洗到薪资技能城市可视化全链路

简介:这是一套面向计算机相关专业学生与项目实战学习者的Python数据采集与分析可视化完整项目,以Boss直聘岗位数据为对象,适合用作毕业设计、课程设计或期末大作业。资源包共38个文件,约246KB,以13个py源码文件为核心&…

2026/10/10 0:00:40 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:25 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 1:36:08 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 11:14:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 5:23:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 10:38:42 阅读更多 →