我希望能够通过
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] => [email protected]
)
)
)
)
我有两种方法,
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 always false
return $bool;
});
}
return $array;
}
使用示例:
$this->sanitizedResponse($data, ['methodCount', `endDate`]);
应该从数组中删除这些元素。但正如我在评论
sanitizedArray
中提到的,其中 return $bool;
总是导致 false
。
@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
$bool
- 所以只有最后一个比较才算数(这就是为什么您总是得到 false 的原因)。
我会让你的代码更简单这样:
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