如何使用黑名单数组删除值,然后减少剩余值以消除间隙?

这个问题基本上是我之前问题的延伸:

如何减去数组的值但仍处于位置

我有一个数组的输入数组。每个子数组中的值始终由0从无间隙开始的值组成,值递增 1。但是,这些值不一定按顺序排列,并且我需要在执行所需逻辑时保留此顺序。

接下来,我有一个希望从所有子数组中删除的值黑名单。必须删除黑名单数组中存在的任何原始子数组值。

数组的示例输入数组:

$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];

我想要的输出是:

[
    [0, 8, 4, 7, 2, 5, 1, 3, 6, 9],
    [0, 1, 2],
    [0, 2, 3, 1],
    [0, 1, 2],
]

自从我删除数字以来,所有大于的剩余值都3减少了1,并且大于的值都5减少了。22

如果给定子数组中的所有数字都小于黑名单数组中的所有数字,则不需要对该子数组进行任何更改。

我在这里尝试编码https://3v4l.org/lX2MP,但在返回它们的值时我陷入困境。所有数组值都合并在一起。


ABOUTYOU
浏览 120回答 2
2回答

尚方宝剑之说

我将稍微改变你的第二个、第三个和第四个子数组,以更好地演示该行为。利用我对上一个问题的回答中的一项技术,我实际上只是将代码逻辑包装在一个附加循环中array_map()。array_diff()用于立即销毁输入数组中与删除值匹配的任何值。然后array_reduce()使用输入数组的剩余值来迭代并减少任何生成的整数以消除间隙。里面array_reduce(),你会看到$value > $item。此比较将返回trueor false。当布尔值用作数字时,true变为1并false变为0。基本上,我根据每个值与给定的比较来减去0或1减去。$value$deletes$value作为一个具体例子,当处理时10,10大于3,因此变为9,并且10大于,5因此9变为8。这一切都是在不需要预先排序数据的情况下完成的。代码:(演示)$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];var_export(    array_map(        function($array) use ($deletes) {            $result = [];            foreach (array_diff($array, $deletes) as $value) {                $result[] = array_reduce(                    $deletes,                    function ($carry, $item) use ($value) {                        return $carry - ($value > $item);                    },                    $value                );            }            return $result;        },        $arrays    ));这是一种行为方式相同但不太依赖函数式编程的替代方案:(演示)foreach ($arrays as $index => $array) {    $filtered = array_diff($array, $deletes);  // destroy blacked values    foreach ($filtered as $value) {        $originalValue = $value;        foreach ($deletes as $delete) {            $value -= $originalValue > $delete; // reduce to eliminate gaps        }        $result[$index][] = $value;    }}var_export($result);输出(对于任一片段):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,  ),)

阿波罗的战车

要从数组中删除数字并从原始数组中的当前数字中减去小于该数字的计数selectedDeletedNumbers,您可以:对数组进行排序selectedDeletedNumbers。迭代原始数组并使用它binary search来获取小于原始数组中当前数字的数字计数,然后将其减去。如果当前编号存在于 中selectedDeletedNumbers,则取消设置它们。对每个单独的子数组应用上述操作。片段:<?phpfunction subtract(&$arr,$selectedDeletedNumbers){ // pass by reference to edit the same copy of the array    foreach($arr as $index => $val){        $low = 0;$high = count($selectedDeletedNumbers) - 1;        $equal_found = false;        while($low <= $high){            $mid = intval(($low + $high) / 2);            if($selectedDeletedNumbers[$mid] > $val){                $high = $mid - 1;            }else if($selectedDeletedNumbers[$mid] < $val){                $low = $mid + 1;            }else{                $equal_found = true;                unset($arr[$index]); // if equal value, delete it as it your need                break;            }        }            if(!$equal_found){            $arr[$index] -= $low; // delete the offset till where it is greater among your $selectedDeletedNumbers        }    }}$selectedDeletedNumbers = [3,5];sort($selectedDeletedNumbers); // sort to be apply binary search later$arr = [[0, 3, 10, 5, 6, 9, 2, 7, 1, 4, 8, 11], [0, 1], [0, 1], [0, 1]];foreach($arr as &$val){ // pass by reference to edit the same copy of the array    subtract($val,$selectedDeletedNumbers); }print_r($arr);演示: https: //3v4l.org/RMh5U如果您想按顺序重新索引数字,请array_values()最后对每个单独的子数组执行一个操作。
打开App,查看更多内容
随时随地看视频慕课网APP