I have an array of non-empty arrays which contain non-negative integers and I need to remove all rows/subarrays which contain at least one zero.
I know I can use a foreach()
or array_filter()
to make iterated calls of in_array()
, but is there a more elegant/concise approach -- perhaps a functional approach without an anonymous callback?
foreach ($array as $k => $row) {
if (in_array(0, $row)) {
unset($array[$k]);
}
}
Or
array_filter(
$array,
function($row) {
return !in_array(0, $row);
}
)
Sample array:
$array = [
'one' => [20,0,40,0,60],
'two' => [50],
'three' => [0, 0, 0, 0],
'four' => [10, 5],
'five' => [0],
];
Desired output:
['two' => [50], 'four' => [10, 5]]
In all honesty, I think that PHP7.4's arrow function syntax makes the array_filter()
call reasonably concise.
array_filter($array, fn($row) => !in_array(0, $row))
Additionally, iterated calls of !in_array()
with a true
third parameter can distinguish between different types and ensure that only integer-typed zeros are targeted. (Demo)
array_filter($array, fn($row) => !in_array(0, $row, true))
That said, because you have non-empty subarrays, you can use array_product
as the callback name. By multiplying all values in a respective row together, any row containing a zero will result in 0
. Since 0
is a falsey value, array_filter()
will exclude the row from the result array. This approach will work even if there are floats or negative numbers in the subarrays. Be aware that array_product()
will not remove empty rows/subarrays.
Code: (Demo)
var_export(
array_filter($array, 'array_product')
);
Output:
array (
'two' =>
array (
0 => 50,
),
'four' =>
array (
0 => 10,
1 => 5,
),
)
For the slightly altered behavior of only keeping rows that contain at least one non-zero value, array_sum
can be used in the same fashion. This approach will still work with empty subarrays or subarrays containing floats, but should not be trusted if a mix of negative and positive values in a respective subarray is possible. (Demo)
var_export(
array_filter($array, 'array_sum')
);
Output:
array (
'one' =>
array (
0 => 20,
1 => 0,
2 => 40,
3 => 0,
4 => 60,
),
'two' =>
array (
0 => 50,
),
'four' =>
array (
0 => 10,
1 => 5,
),
)