我有一个深度不确定的多维数组。我只想保留一些依赖于路径集合的键,但我需要一个通用的递归函数,而不是硬编码的过滤器。
示例:
$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 作为键)
我编写了一个递归脚本来删除不合格的元素,同时通过引用修改输入数组。如果您引用该函数“返回”修改后的有效负载,您可以在最后
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));
这可以使用递归函数来完成。
之前给出:
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;
}