数组中包含零的 Remove/Filter 行

Remove/Filter rows from array which contain a zero

我有一组包含非负整数的非空数组,我需要删除所有包含至少一个零的 rows/subarrays。

我知道我可以使用 foreach()array_filter() 来迭代调用 in_array(),但是是否有更多 elegant/concise 的方法——也许是函数式方法没有匿名回调?

foreach ($array as $k => $row) {
    if (in_array(0, $row)) {
        unset($array[$k]);
    }
}

array_filter(
    $array,
    function($row) {
        return !in_array(0, $row);
    }
)

示例数组:

$array = [
    'one' => [20,0,40,0,60],
    'two' => [50],
    'three' => [0, 0, 0, 0],
    'four' => [10, 5],
    'five' => [0],
];

期望的输出:

['two' => [50], 'four' => [10, 5]]

老实说,我认为 PHP7.4 的箭头函数语法使 array_filter() 调用相当简洁。

array_filter($array, fn($row) => !in_array(0, $row))

也就是说,因为您有 non-empty 个子数组,所以您可以使用 array_product 作为回调名称。通过将相应行中的所有值相乘,任何包含零的行将导致 0。由于 0 是一个错误值,因此 array_filter() 将从结果数组中排除该行。即使子数组中有浮点数或负数,这种方法也能奏效。请注意 array_product() 不会删除空 rows/subarrays.

代码:(Demo)

var_export(
    array_filter($array, 'array_product')
);

输出:

array (
  'two' => 
  array (
    0 => 50,
  ),
  'four' => 
  array (
    0 => 10,
    1 => 5,
  ),
)

对于仅保留包含至少一个 non-zero 值的行的稍微改变的行为,可以以相同的方式使用 array_sum。这种方法仍然适用于空子数组或包含浮点数的子数组,但如果在相应子数组中可能混合使用负值和正值,则不应信任此方法。 (Demo)

var_export(
    array_filter($array, 'array_sum')
);

输出:

array (
  'one' => 
  array (
    0 => 20,
    1 => 0,
    2 => 40,
    3 => 0,
    4 => 60,
  ),
  'two' => 
  array (
    0 => 50,
  ),
  'four' => 
  array (
    0 => 10,
    1 => 5,
  ),
)