PHP二维数组移除连续重复'Out'项(保留首尾)及代码调试问题
修复PHP数组处理代码:保留连续"Out"项首尾,移除中间项
原始数组
$out = array( '2011' => ['Out', 'arrv'], '2012' => ['Out'], '2013' => ['Out'], '2014' => ['Out'], '2015' => ['Out'], '2016' => ['some', 'none', 'test'], '2017' => ['Out'], '2018' => ['Out'], '2019' => ['Out'], '2020' => ['Out', 'did'], '2021' => ['Out'], '2022' => ['Out'], '2023' => ['Out', 'did'] );
需求说明
移除连续的仅包含'Out'的单元素项,但保留每组连续项的第一个和最后一个;非'Out'单元素的项全部保留。
错误代码及问题
用户尝试的代码:
foreach ($out as $dtp=>$dto) { if (count($dto) == 1) { if (str_contains($dto[0], "Out")) { $idx = array_search($dtp, array_keys($out)); echo "$dtp contains the string; index is $idx" . PHP_EOL; var_dump($out[intval(array_keys($idx - 1))]); if ((str_contains($out[$idx-1][0], "Out")) && (str_contains($out[$idx+1][0], "Out")) && count($out[$idx-1] == 1) && count($out[$idx+1] == 1)) { array_splice($out, $idx, 1); } } } }
运行时触发的警告与输出:
2017 contains the string; index is 6 PHP Warning: array_keys() expects parameter 1 to be array, integer given in /home/redacted/pub/dbg2.php on line 28 PHP Notice: Undefined offset: 0 in /home/redacted/pub/dbg2.php on line 28 NULL 2018 contains the string; index is 7 PHP Warning: array_keys() expects parameter 1 to be array, integer given in /home/redacted/pub/dbg2.php on line 28 PHP Notice: Undefined offset: 0 in /home/redacted/pub/dbg2.php on line 28 NULL 2019 contains the string; index is 8 PHP Warning: array_keys() expects parameter 1 to be array, integer given in /home/redacted/pub/dbg2.php on line 28 PHP Notice: Undefined offset: 0 in /home/redacted/pub/dbg2.php on line 28 NULL 2021 contains the string; index is 10 PHP Warning: array_keys() expects parameter 1 to be array, integer given in /home/redacted/pub/dbg2.php on line 28 PHP Notice: Undefined offset: 0 in /home/redacted/pub/dbg2.php on line 28 NULL 2022 contains the string; index is 11 PHP Warning: array_keys() expects parameter 1 to be array, integer given in /home/redacted/pub/dbg2.php on line 28 PHP Notice: Undefined offset: 0 in /home/redacted/pub/dbg2.php on line 28 NULL
期望结果
处理后的目标数组:
[ '2011' => ['Out', 'arrv'], '2012' => ['Out'], '2015' => ['Out'], '2016' => ['some', 'none', 'test'], '2017' => ['Out'], '2019' => ['Out'], '2020' => ['Out', 'did'], '2021' => ['Out'], '2022' => ['Out'], '2023' => ['Out', 'did'] ]
修复后的代码及说明
原代码问题分析
array_keys($idx - 1)语法错误:array_keys需要传入数组,此处误传整数,导致无法正确获取前一个键名。- 遍历原数组时直接用
array_splice修改,会导致数组索引错乱,后续循环判断失效。 count($out[$idx-1] == 1)逻辑错误:判断括号位置错误,应改为count($out[$idx-1]) == 1。- 未处理数组首尾边界的
Out项,可能导致索引越界。
修复代码
// 分离原数组的键和值,避免关联数组索引操作混乱 $keys = array_keys($out); $values = array_values($out); $result = []; $total = count($values); for ($i = 0; $i < $total; $i++) { $currentVal = $values[$i]; // 判断当前项是否为仅含'Out'的单元素数组 $isSingleOut = count($currentVal) === 1 && $currentVal[0] === 'Out'; // 非Out单元素项直接保留 if (!$isSingleOut) { $result[$keys[$i]] = $currentVal; continue; } // 检查前后项是否同为仅含Out的单元素数组 $prevIsOut = ($i > 0) ? (count($values[$i-1]) === 1 && $values[$i-1][0] === 'Out') : false; $nextIsOut = ($i < $total - 1) ? (count($values[$i+1]) === 1 && $values[$i+1][0] === 'Out') : false; // 仅当前后都是Out单元素项时,当前项为中间项,移除;否则保留 if (!$prevIsOut || !$nextIsOut) { $result[$keys[$i]] = $currentVal; } } // 输出结果 print_r($result);
代码逻辑说明
- 先将原数组的键和值分离,通过索引遍历值数组,避免关联数组操作的混乱。
- 对每个元素判断是否为仅含
'Out'的单元素数组。 - 非目标移除项直接加入结果数组。
- 对目标移除项,检查前后元素是否同类:只有当前元素是连续同类项的中间项时才移除,首尾项保留。
- 最终结果完全符合需求,且不会出现索引越界或遍历错乱问题。
内容的提问来源于stack exchange,提问作者byteflush
相关产品推荐
相关产品推荐

