通过键递归地从嵌套数组中删除元素(array_filter_recursive)

时间:2019-05-10 11:59:32

标签: php arrays

我希望能够通过key

从多维数组中删除元素

此类数组的示例可以是:

Array
(
    [data] => Array
        (
            [todo] => code review
            [schedule] => Array
                (
                    [endDate] => 2019-05-10T00:00:00+01:00
                    [startDate] => 2019-05-09T00:00:00+01:00
                )

            [codeDetails] => Array
                (
                    [language] => PHP
                    [type] => class
                    [abstract] => true
                    [methodCount] => Array
                        (
                            [public] => 3
                            [protected] =>
                            [private] => 1
                        )

                    [LOC] => 123
                    [cyclomaticComplexity] => 4
                    [author] => Array (
                            [name] => Lukasz
                            [email] => private@tulik.io
                        )
                )

        )
)

我有两种方法,recursiveArrayDelete删除回调返回true的所有元素:

private function recursiveArrayDelete(array &$array, callable $callback): array
{
    foreach ($array as $key => &$value) {
        if (is_array($value)) {
            $value = $this->recursiveArrayDelete($value, $callback);
        }
        if ($callback($value, $key)) {
            unset($array[$key]);
        }
    }

    return $array;
}

第二,从restrictedProperties中删除array中所有包含的属性:

private function sanitizedArray(array &$array, array &$restrictedProperties): array
{
    foreach ($restrictedProperties as $restrictedProperty) {
        $this->recursiveArrayDelete(
            $array,
             static function () use ($array, $restrictedProperty): bool {
                array_walk_recursive(
                    $array,
                    static function ($value, $key) use (&$bool, $restrictedProperty) {
                         // here $bool is as expected from condition
                         $bool = $key === $restrictedProperty;
                     });
                  // here is alwalys false
                 return $bool; 
             });
    }

    return $array;
}

用法示例:

$this->sanitizedResponse($data, ['methodCount', `endDate`]);

应从数组中删除这些元素。但正如我在com {sanitizedArray一文中提到的,其中return $bool;总是产生false

2 个答案:

答案 0 :(得分:2)

您做得很好。注意,您有两个问题:首先在两个函数中都进行递归,然后重新分配给$bool-因此只有最后一个比较才是计数(这就是为什么总是出现错误的原因)。

我将通过以下方式使您的代码更简单:

function array_filter_recursive(array &$array, callable $callback) {
    foreach ($array as $key => &$value) {
        if ($callback($key, $value)) unset($array[$key]);
        else if (is_array($value)) array_filter_recursive($value, $callback);
    }
}

function sanitizedArray(&$arr, $restricted, $keys = false) {
    foreach($restricted as $val) {
        array_filter_recursive($arr, function($k, $v) use ($val, $keys) {return $keys ? ($val === $k) : ($val === $v);});
    }
}

现在您可以简单地将其用作示例:$this->sanitizedResponse($data, ['methodCount', 'endDate'], true);

以下是带有伪数据的实时示例:3v4l

答案 1 :(得分:2)

@dWinder的答案几乎是完美的。但是,当我使用它的时候多了一点,我注意到它不会删除给定“受限属性”下的数组。

让我们假设所有"D"元素都将被删除:

dWinder的解决方案将导致:

Array
(
    [A] => aa
    [B] => Array
        (
            [A] => aaa
            [B] => bb
        )

    [C] => cc
    [D] => Array
        (
            [E] => ee
        )

)

"D"下的数组仍然存在。但是,当您将if的条件和动作切换为else if的条件和动作时,会得到(假定!)所需的结果:

Array
(
    [A] => aa
    [B] => Array
        (
            [A] => aaa
            [B] => bb
        )

    [C] => cc
)

因此,改进的功能代码应如下所示(我在这里引用@dWinder解决方案的某些部分):

$arr = array("A" => "aa", "B" => ["A" => "aaa", "B" => "bb"], "C" => "cc", "D" => ["E" =>"ee"]);

function array_filter_recursive(array &$array, callable $callback) {
    foreach ($array as $key => &$value) {
        if ($callback($key, $value))   unset($array[$key]);
        else if (is_array($value))     array_filter_recursive($value, $callback);
    }
}

function sanitizedArray(&$arr, $restrictedProperties) {
    foreach($restrictedProperties as $prop) {
        array_filter_recursive($arr, function($k, $v) use ($prop) {return $prop == $k;});
    }
}
sanitizedArray($arr, ["D"]);
print_r($arr);

参见此处的演示:https://3v4l.org/05tc7