How to Run Array_Filter Recursively in a PHP Array

How to run array_filter recursively in a PHP array?

Should work

$count = array_sum(array_map(function ($item) {
return ((int) !is_null($item['pts_m'])
+ ((int) !is_null($item['pts_mreg'])
+ ((int) !is_null($item['pts_cg']);
}, $array);

or maybe

$count = array_sum(array_map(function ($item) {
return array_sum(array_map('is_int', $item));
}, $array);

There are definitely many more possible solutions. If you want to use array_filter() (without callback) remember, that it treats 0 as false too and therefore it will remove any 0-value from the array.

If you are using PHP in a pre-5.3 version, I would use a foreach-loop

$count = 0;
foreach ($array as $item) {
$count += ((int) !is_null($item['pts_m'])
+ ((int) !is_null($item['pts_mreg'])
+ ((int) !is_null($item['pts_cg']);
}

Update

Regarding the comment below:

Thx @kc I actually want the method to remove false, 0, empty etc

When this is really only, what you want, the solution is very simple too.
But now I don't know, how to interpret

My expected result here would be 5.

Anyway, its short now :)

$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);

The resulting array looks like

Array
(
[147] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)
[158] => Array
(
)

[159] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)

)

PHP array_filter Recursive

You only want to remove a key if it's not named access and the value is not a nested array. This way, you keep any intermediate arrays.

You can't use array_filter(), because it only receives the values, not the keys. So do it in your foreach loop.

function array_filter_recursive($input)
{
foreach ($input as $key => &$value) {
if (is_array($value)) {
$value = array_filter_recursive($value);
if (empty($value)) {
unset($input[$key]));
}
} elseif ($key != 'access') {
unset($input[$key]);
}
}
return $input;
}

How to use array_filter() function recursively on a multi-dimensional array in order to remove the key-value pairs that contains null values?

Unfortunately there's no built in function that allows you to walk an array recursively and unset keys. The closest is array_walk_recursive. This falls short, however, as the array is passed in as a reference, and all variable assignment is done within the callable function. This means that while you can mutate the element, you can't actually unset it, without adding bloat code.

Instead, we can use a function that was forked from array_walk_recursive that performs key unsetting. The function that is callabe returns a boolean true/false indicating whether or not to remove the element. We simply perform our comparison and return true, otherwise return false.

function walk_recursive_remove (array $array, callable $callback) {
foreach ($array as $k => $v) {
if (is_array($v)) {
$array[$k] = walk_recursive_remove($v, $callback);
} else {
if ($callback($v, $k)) {
unset($array[$k]);
}
}
}

return $array;
}

Then we just create our own function that accepts the value of the iterated element and it's key, then performs the NULL check and returns our true/false.

function unset_null_children($value, $key){
return $value === NULL;
}

Hopefully this is what you're looking for.

Filter recursive array and only remove NULL value

You could combine array_map and array_filter in an recursive called function. Something like this could work for you.

function filterNotNull($array) {
$array = array_map(function($item) {
return is_array($item) ? filterNotNull($item) : $item;
}, $array);
return array_filter($array, function($item) {
return $item !== "" && $item !== null && (!is_array($item) || count($item) > 0);
});
}

Php Array_filter to unset key values from array of arrays

Here is an example of a recursive foreach based solution to your code working off the data set you provided.

    $sourceArray = array("a" => 3, "b" => 0, "c" => array("1" => "aa", "2" => 1, "3" => array("a1" => 6, "a2" => 5781, "a3" => array("1" => 0, "2" => 19550, "3" => 5781)), array( "a1" => 1, "a2" => 5781, "a3" =>array("1" => 0, "2" => 19550, "3" => 5781 ))), array( "1" => "aa", "2" => 1, "3" => array( array( "a1" => 6, "a2" => 5781, "a3" => array( "1" => 0, "2" => 19550,"3" => 5781))), array( "a1" => 1, "a2" => 5781, "a3" =>array(  "1" => 0, "2" => 19550, "3" => 5781))));

print_r($sourceArray,1);

function removeKeys($keys, $sourceData) {

foreach ($sourceData as $key=>$val) {

if (in_array($key, $keys, true)) {
unset($sourceData[$key]);
} else if (is_array($val)) {
$sourceData[$key] = removeKeys($keys, $sourceData[$key]);
}
}
return $sourceData;
}

$keysToRemove = array("b","2","a2");

$newArray = removeKeys($keysToRemove, $sourceArray);

print_r($newArray);

Simple to implement though getting your data in was a bit of a challenge. I did notice a "bug" in this example in that if the key is "0" in the original array it still gets deleted even if it's not in the $keys array.

But I'm assuming that this example is sufficient to answer your question and that my stated edge case will not occur (ie, "0" is not a key value in your array.) If you do use "0" as a key you can add additional logic to trap that case but it would slow the function down a bit so I'll leave that choice up to you.

(Note, the bug referred to above is fixed now and in the code... see notes below for solution from original poster)

Recursively remove elements from nested array by key (array_filter_recursive)

@dWinder's answer is almost perfect. But when I played around with it a bit more I noticed that it would not delete an array under a given "restricted property".

Let us assume that all "D"-elements were to be removed:

dWinder's solution would result in:

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

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

)

The array under "D" is still there. But when you switch the if condition and action with that of the else if you get the (assumed!) desired result:

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

[C] => cc
)

So, the improved function code should look something like this (I am quoting parts of @dWinder's solution here):

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

See here for a demo: https://3v4l.org/05tc7

PHP - How to remove empty entries of an array recursively?

Try this code:

<?php
function array_remove_empty($haystack)
{
foreach ($haystack as $key => $value) {
if (is_array($value)) {
$haystack[$key] = array_remove_empty($haystack[$key]);
}

if (empty($haystack[$key])) {
unset($haystack[$key]);
}
}

return $haystack;
}

$raw = array(
'firstname' => 'Foo',
'lastname' => 'Bar',
'nickname' => '',
'birthdate' => array(
'day' => '',
'month' => '',
'year' => '',
),
'likes' => array(
'cars' => array('Subaru Impreza WRX STi', 'Mitsubishi Evo', 'Nissan GTR'),
'bikes' => array(),
),
);

print_r(array_remove_empty($raw));


Related Topics



Leave a reply



Submit