如何用黑名单数组移除值并缩减剩余值消除间隙(代码求助)
解决多维数组的黑名单移除与数值缩减问题
我明白你遇到的麻烦了——之前的代码把不同子数组的数值混到一起了,核心问题是没给每个子数组做独立处理。咱们先把需求理清楚,再给出通用且正确的实现方案:
需求明确
- 输入是多维数组,每个子数组的数值是从0开始无间隙递增(步长1)但顺序打乱的
- 需要移除所有出现在黑名单里的数值,同时严格保留原数组的顺序
- 缩减规则:剩余数值要减去「比它小的黑名单元素的总数量」——比如黑名单是[3,5],数值4比1个黑名单元素(3)大,所以4-1=3;数值6比2个黑名单元素(3、5)大,所以6-2=4,完全匹配你给出的示例逻辑
通用PHP实现方案
这个方案不管黑名单元素数量、数值如何变化都能适配,而且每个子数组独立操作,绝不会出现元素合并的问题:
<?php $arrays = [ [0, 3, 10, 5, 6, 9, 2, 7, 1, 4, 8, 11], [0, 1, 2, 3], [0, 5, 2, 4, 3, 1], [0, 1, 3, 2] ]; $deletes = [3, 5]; // 先给黑名单排序,统计时可以提前终止循环,提升效率 sort($deletes); $result = array_map(function($subArr) use ($deletes) { // 第一步:过滤黑名单元素,保留原顺序 $filteredItems = array_filter($subArr, function($val) use ($deletes) { return !in_array($val, $deletes); }); // 第二步:对每个剩余元素计算缩减后的值 $reducedItems = array_map(function($val) use ($deletes) { $smallerDelCount = 0; foreach ($deletes as $del) { if ($del < $val) { $smallerDelCount++; } else { // 黑名单已排序,后面的数都不小于当前值,直接跳出循环 break; } } return $val - $smallerDelCount; }, $filteredItems); // 重置索引为连续数字,和示例输出格式一致 return array_values($reducedItems); }, $arrays); print_r($result); ?>
代码细节说明
- 黑名单排序:把黑名单从小到大排序后,统计比当前元素小的黑名单数量时,一旦遇到不小于当前元素的数就停止循环,不用遍历整个黑名单,效率更高
- 子数组独立处理:用
array_map遍历每个子数组,每个子数组的过滤、缩减逻辑都是独立执行的,从根源避免了元素合并问题 - 通用缩减逻辑:不再硬编码“大于3减1、大于5减2”,而是动态统计比当前元素小的黑名单数量,不管黑名单怎么变化,逻辑都能适配
- 索引重置:用
array_values把过滤后的数组索引改成连续数字,和你期望的输出完全匹配
测试输出结果
运行代码后,输出和你给出的期望完全一致:
Array ( [0] => Array ( [0] => 0 [1] => 8 [2] => 4 [3] => 7 [4] => 2 [5] => 5 [6] => 1 [7] => 3 [8] => 6 [9] => 9 ) [1] => Array ( [0] => 0 [1] => 1 [2] => 2 ) [2] => Array ( [0] => 0 [1] => 2 [2] => 3 [3] => 1 ) [3] => Array ( [0] => 0 [1] => 1 [2] => 2 ) )
之前代码合并问题的原因
大概率是你之前的代码没有给每个子数组维护独立的结果容器,比如用了一个全局数组来存储所有处理后的元素,而不是为每个子数组生成单独的结果。上面的方案通过array_map为每个子数组生成独立的处理结果,彻底解决了这个问题。
内容的提问来源于stack exchange,提问作者Marky
相关产品推荐
相关产品推荐

