使用包含通配符的白名单关键路径的二维数组递归过滤多维数组

问题描述 投票:0回答:2

我有一个深度不确定的多维数组。我只想保留一些依赖于路径集合的键,但我需要一个通用的递归函数,而不是硬编码的过滤器。

示例:

$originalArray = array(
    'key1' => array(
        'key1' => 'value1',
        'key2' => 'value2',
    ),
    'key2' => array(
        'key1' => 'value3',
        'key2' => 'value4',
        'key3' => array(
            'key1' => 'value5',
            'key2' => array(
                'key1' => 'value6',
                'key2' => 'value',
            ),
        ),
    ),
    'key3' => array(
        "key1" => "value1",
        "key2" => array(
            array(
                'key1' => 'value1',
                'key2' => 'value2',
                'key3' => 'value2',
            ),
            array(
                'key1' => 'value1',
                'key2' => 'value2',
                'key3' => 'value3',
            ),
        )
    ),
);

$pathsToRetain = array(
    array('key1', 'key1'),
    array('key2', 'key1'),
    array('key2', 'key3', 'key1'),
    array('key2', 'key3', 'key2', 'key1'),
    array("key3", "key2", "*", 'key1'),
    array("key3", "key2", "*", 'key3')
);

$this->filterArrayByPath($originalArray, pathsToRetain);

结果应该是:

$result = array(
    'key1' => array(
        'key1' => 'value1',
    ),
    'key2' => array(
        'key1' => 'value3',
        'key3' => array(
            'key1' => 'value5',
            'key2' => array(
                'key1' => 'value6',
            ),
        ),
    ),
    'key3' => array(
        "key2" => array(
            array(
                'key1' => 'value1',
                'key3' => 'value2',
            ),
            array(
                'key1' => 'value1',
                'key3' => 'value3',
            ),
        )
    ),
);

其中一个困难是没有键的数组的通配符(key3->key2包含没有键的数组,我想将过滤器应用于它们两个,或者如果不是通配符则使用 0, 1, 3 作为键)

php arrays recursion multidimensional-array filter
2个回答
0
投票

我编写了一个递归脚本来删除不合格的元素,同时通过引用修改输入数组。如果您引用该函数“返回”修改后的有效负载,您可以在最后

return $array
;但请记住,您的原始输入数组将被此函数改变。

如果您想查看内部进度,演示链接有一些额外的注释检查点。

脚本将迭代输入数组的当前级别并检查路径数组中每行的第一个值。如果找到符合条件的键,则会设置一个标志以不取消设置该元素。如果元素符合条件并且有更多路径要遍历,则以减少的参数再次调用该函数。

代码:(演示

function filterArrayByPath(&$array, $pathsToRetain) {
    foreach ($array as $k => &$v) {
        $soFarSoGood = false;
        $paths = [];
        foreach ($pathsToRetain as $path) {
            $requiredKey = array_shift($path);
            if (in_array($requiredKey, ['*', $k])) {
                $soFarSoGood = true;
                if ($path) {
                    $paths[] = $path;
                } else {
                    break;
                }
            }
        }
        if (!$soFarSoGood) {
            unset($array[$k]);
        } elseif ($paths) {
            filterArrayByPath($v, $paths);
        }
    }
    //return $array;
}
filterArrayByPath($originalArray, $pathsToRetain);
var_export($originalArray);
// if returning the array: var_export(filterArrayByPath($originalArray, $pathsToRetain));

-1
投票

这可以使用递归函数来完成。

之前给出:

function filterArrayByPath($array, $pathsToRetain) {
    $filteredArray = [];

    foreach ($pathsToRetain as $path) {
        $currentArray = &$array;
        $validPath = true;

        foreach ($path as $key) {
            if ($key === '*') {
                $currentArray = array_merge_recursive($currentArray, array_fill_keys(array_keys($currentArray), []));
            } elseif (is_array($currentArray) && array_key_exists($key, $currentArray)) {
                $currentArray = &$currentArray[$key];
            } else {
                $validPath = false;
                break;
            }
        }

        if ($validPath) 
            $filteredArray = array_merge_recursive($filteredArray, $currentArray);
        
    }

    return $filteredArray;
}
© www.soinside.com 2019 - 2024. All rights reserved.