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;
}
Answer from Barmar on Stack OverflowYou 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;
}
The solution can be a little leaner than Barmar's answer.
As you iterate, if you encounter an subarray, recursively traverse. Otherwise, when you encounter a non-array and its key is not access, then prune it.
My snippet will use the magic __FUNCTION__ to avoid the bloat of repeating the verbose yet indicative function name.
Code: (Demo)
function removeIfNotArrayAndNotSiblingOfAccess($array) {
foreach ($array as $key => &$value) {
if (is_array($value)) {
$value = (__FUNCTION__)($value);
} elseif ($key != 'access') {
unset($array[$key]);
}
}
return $array;
}
var_export(removeIfNotArrayAndNotSiblingOfAccess($array));
From the PHP array_filter documentation:
//This function filters an array and remove all null values recursively.
<?php
function array_filter_recursive($input)
{
foreach ($input as &$value)
{
if (is_array($value))
{
$value = array_filter_recursive($value);
}
}
return array_filter($input);
}
?>
//Or with callback parameter (not tested) :
<?php
function array_filter_recursive($input, $callback = null)
{
foreach ($input as &$value)
{
if (is_array($value))
{
$value = array_filter_recursive($value, $callback);
}
}
return array_filter($input, $callback);
}
?>
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
)
)
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;
}
The solution can be a little leaner than Barmar's answer.
As you iterate, if you encounter an subarray, recursively traverse. Otherwise, when you encounter a non-array and its key is not access, then prune it.
My snippet will use the magic __FUNCTION__ to avoid the bloat of repeating the verbose yet indicative function name.
Code: (Demo)
function removeIfNotArrayAndNotSiblingOfAccess($array) {
foreach ($array as $key => &$value) {
if (is_array($value)) {
$value = (__FUNCTION__)($value);
} elseif ($key != 'access') {
unset($array[$key]);
}
}
return $array;
}
var_export(removeIfNotArrayAndNotSiblingOfAccess($array));
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);
});
}
Don't need to reinvent recursion yourself. You can use RecursiveCallbackFilterIterator:
$iterator = new RecursiveIteratorIterator(
new RecursiveCallbackFilterIterator(
new RecursiveArrayIterator($arr),
function ($value) {
return $value !== null && $value !== '';
}
)
);
$result = iterator_to_array($iterator);
Here is working demo.
You should try to use as much stuff from Standard PHP Library (SPL) as you can.
UPDATE: As it is stated in the comments, the solution with iterator not actually suits for this purpose.
In the comments to the array_walk_recursive function you can find the implementation of walk_recursive_remove function:
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;
}
This generalized version of recursion function takes criteria in the form of callback. Having this function you can remove empty elements like this:
$result = walk_recursive_remove($arr, function ($value) {
return $value === null || $value === '';
});
Here is working demo.