键值相同时如何计算两个多维数组的差异?已尝试多方案未解决
解决多维数组基于键值匹配的差异对比问题
嘿,我懂你现在的困扰——多维数组的差异对比本来就比一维数组麻烦,尤其是还要严格基于键值匹配的情况。我之前做项目的时候也碰到过几乎一模一样的场景,给你分享个针对性的解决方案,应该能解决你的问题。
先明确场景和示例数组
首先咱们把你提到的数组补全,方便测试:
// 数据库里的原始数据(DbData) $dbData = [ "phase-5[]" => [ '1' => "Admin Phase 1 Task 1", '2' => "Admin Phase 1 Task 2" ], "phase-6[]" => [ '1' => "Admin Phase 2 Task 1", '2' => "Admin Phase 2 Task 2" ], "phase-7[]" => [ '1' => "Admin Phase 3 Task 1" ] ]; // 前端传过来的新数据(ajaxData) $ajaxData = [ "phase-5[]" => [ '1' => "Admin Phase 1 Task 1 (Updated)", // 内容修改 '2' => "Admin Phase 1 Task 2" ], "phase-6[]" => [ '1' => "Admin Phase 2 Task 1", '3' => "Admin Phase 2 Task 3" // 新增任务 ], "phase-8[]" => [ // 新增整个phase '1' => "Admin Phase 4 Task 1" ] ];
核心对比函数
这个函数会分层处理:先对比外层的phase键,再对比每个phase下的任务键值对,最后返回一个包含新增、删除、修改三类差异的数组:
function compareMultiArrays($original, $new) { $differences = [ 'added' => [], 'removed' => [], 'modified' => [] ]; // 获取所有外层键的并集,确保不会漏掉任何一个phase $allPhaseKeys = array_unique(array_merge(array_keys($original), array_keys($new))); foreach ($allPhaseKeys as $phaseKey) { // 情况1:该phase只在新数组里(新增的phase) if (!isset($original[$phaseKey]) && isset($new[$phaseKey])) { $differences['added'][$phaseKey] = $new[$phaseKey]; continue; } // 情况2:该phase只在原数组里(删除的phase) if (isset($original[$phaseKey]) && !isset($new[$phaseKey])) { $differences['removed'][$phaseKey] = $original[$phaseKey]; continue; } // 情况3:两边都有这个phase,对比内层任务 $originalTasks = $original[$phaseKey]; $newTasks = $new[$phaseKey]; $allTaskKeys = array_unique(array_merge(array_keys($originalTasks), array_keys($newTasks))); foreach ($allTaskKeys as $taskKey) { // 任务只在新数组里(新增任务) if (!isset($originalTasks[$taskKey]) && isset($newTasks[$taskKey])) { $differences['added'][$phaseKey][$taskKey] = $newTasks[$taskKey]; } // 任务只在原数组里(删除任务) elseif (isset($originalTasks[$taskKey]) && !isset($newTasks[$taskKey])) { $differences['removed'][$phaseKey][$taskKey] = $originalTasks[$taskKey]; } // 任务键存在但内容不同(修改任务) elseif ($originalTasks[$taskKey] !== $newTasks[$taskKey]) { $differences['modified'][$phaseKey][$taskKey] = [ 'old' => $originalTasks[$taskKey], 'new' => $newTasks[$taskKey] ]; } } } // 过滤掉空的分类,让结果更干净 foreach ($differences as $key => $value) { if (empty($value)) { unset($differences[$key]); } } return $differences; }
测试函数并查看结果
调用函数然后打印结果:
$diff = compareMultiArrays($dbData, $ajaxData); print_r($diff);
输出结果会是:
Array ( [added] => Array ( [phase-6[]] => Array ( [3] => Admin Phase 2 Task 3 ) [phase-8[]] => Array ( [1] => Admin Phase 4 Task 1 ) ) [removed] => Array ( [phase-7[]] => Array ( [1] => Admin Phase 3 Task 1 ) [phase-6[]] => Array ( [2] => Admin Phase 2 Task 2 ) ) [modified] => Array ( [phase-5[]] => Array ( [1] => Array ( [old] => Admin Phase 1 Task 1 [new] => Admin Phase 1 Task 1 (Updated) ) ) ) )
关键注意事项
- 确保外层的phase键完全一致(比如你示例里的
phase-5[],括号不能少,大小写也要匹配),否则会被当成不同的phase - 如果你的数组层级更深,可以把内层的对比逻辑改成递归调用,这个函数很容易扩展
- 函数里用了
!==来对比值,会严格区分类型(比如数字和字符串的1会被当成不同),如果不需要严格类型对比,可以改成!=
内容的提问来源于stack exchange,提问作者WebRence
相关产品推荐
相关产品推荐

