如果您想快速删除 NULL、FALSE 和空字符串(""),但保留值为 0(零),您可以使用标准 PHP 函数 strlen 作为回调函数
例如
<?php
// 删除所有 NULL、FALSE 和空字符串,但保留 0(零)值
$result = array_filter( $array, 'strlen' );
?>
(PHP 4 >= 4.0.6, PHP 5, PHP 7, PHP 8)
array_filter — 使用回调函数过滤数组元素
遍历 array
中的每个值,并将它们传递给 callback
函数。如果 callback
函数返回 true
,则将 array
中的当前值返回到结果 array 中。
数组键被保留,如果 array
是索引的,可能会导致间隙。可以使用 array_values() 函数重新索引结果 array。
array
要迭代的数组
callback
要使用的回调函数
如果没有提供 callback
,则将删除 array
中的所有空条目。有关 PHP 在此情况下如何定义空的,请参阅 empty()。
mode
确定要发送到 callback
的参数的标志
ARRAY_FILTER_USE_KEY
- 将键作为 callback
的唯一参数传递,而不是值
ARRAY_FILTER_USE_BOTH
- 将值和键都作为参数传递给 callback
,而不是值
0
,它将值作为 callback
的唯一参数传递。
返回已过滤的数组。
版本 | 描述 |
---|---|
8.0.0 |
callback 现在可以为空。 |
8.0.0 | 如果 callback 期望将参数按引用传递,则此函数现在将发出 E_WARNING 。 |
示例 #1 array_filter() 示例
<?php
function odd($var)
{
// 返回输入整数是否为奇数
return $var & 1;
}
function even($var)
{
// 返回输入整数是否为偶数
return !($var & 1);
}
$array1 = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5];
$array2 = [6, 7, 8, 9, 10, 11, 12];
echo "奇数 :\n";
print_r(array_filter($array1, "odd"));
echo "偶数:\n";
print_r(array_filter($array2, "even"));
?>
上面的示例将输出
Odd : Array ( [a] => 1 [c] => 3 [e] => 5 ) Even: Array ( [0] => 6 [2] => 8 [4] => 10 [6] => 12 )
示例 #2 array_filter() 不使用 callback
<?php
$entry = [
0 => 'foo',
1 => false,
2 => -1,
3 => null,
4 => '',
5 => '0',
6 => 0,
];
print_r(array_filter($entry));
?>
上面的示例将输出
Array ( [0] => foo [2] => -1 )
示例 #3 array_filter() 带有 mode
<?php
$arr = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
var_dump(array_filter($arr, function($k) {
return $k == 'b';
}, ARRAY_FILTER_USE_KEY));
var_dump(array_filter($arr, function($v, $k) {
return $k == 'b' || $v == 4;
}, ARRAY_FILTER_USE_BOTH));
?>
上面的示例将输出
array(1) { ["b"]=> int(2) } array(2) { ["b"]=> int(2) ["d"]=> int(4) }
如果数组在回调函数中被更改(例如,添加或取消设置元素),则此函数的行为未定义。
如果您想快速删除 NULL、FALSE 和空字符串(""),但保留值为 0(零),您可以使用标准 PHP 函数 strlen 作为回调函数
例如
<?php
// 删除所有 NULL、FALSE 和空字符串,但保留 0(零)值
$result = array_filter( $array, 'strlen' );
?>
请注意,经过过滤的数组不再编码为 json 数组,因为索引不再连续
$a = ['a', 'b', 'c'];
var_dump(json_encode($a)); // ["a","b","c"]
$a = array_filter($a, function ($x) { return $x == 'b'; });
var_dump(json_encode($a)); // {"1": "b"}
您可以使用 array_values 获取一个连续的数组
var_dump(json_encode(array_values($a))); // ["b"]
上面已经清楚地说明了这一点,但请确保您永远不会忘记,当设置 ARRAY_FILTER_USE_BOTH 时,回调参数的顺序是值、键 - 而不是键、值。这将为您节省一些时间。
如果您像我一样,由于使用了按位运算符 (&) 而难以理解示例 #1,以下是一个解释。
有问题的部分是这个回调函数
<?php
function odd($var)
{
// 返回输入整数是否为奇数
return($var & 1);
}
?>
如果给定一个整数,则此函数返回整数 1(如果 $var 为奇数)和整数 0(如果 $var 为偶数)。
单个按位与运算符 & 是按位与运算符。它的工作原理是获取两个参数的二进制表示,并使用 AND 位对位地比较它们。如果 $var = 45,那么由于 45 的二进制表示为 101101,所以操作看起来像这样
45 的二进制表示:101101
1 的二进制表示:000001
------
结果:000001
只有当 $var 二进制表示的最后一位变为零(意味着值为偶数)时,结果才会变为 000000,即零的表示。
请记住,从 PHP 7.4 及更高版本开始,您可以使用箭头函数作为参数。
例如,如果您想保留大于 10 的值
<?php
$arr = array_filter($numbers, fn($n) => $n > 10);
?>
此外,结合使用键标志来裁剪某些键
<?php
$arr = array_filter($entries, fn($key) => !in_array($key, ['key1', 'key5']), ARRAY_FILTER_USE_KEY);
?>
等等。
array_filter 保留键的事实使得将数组分割成 [通过测试的元素,未通过测试的元素] 变得非常容易。本质上
<?php
function partition($array, $test)
{
$pass = array_filter($array, $test);
$fail = array_diff_key($array, $pass);
return [false => $fail, true => $pass];
}
?>
array_diff_key 调用是关键;如所示索引返回的数组允许像 "$failures = $partition[false];" 这样的行执行正确的事情(当然,布尔值被转换为整数,但这很一致且自说明)。
PHP 的一些数组函数在所谓的函数式编程语言中发挥着重要作用,在这些语言中,它们以稍微不同的名称出现
<?php
array_filter() -> filter(),
array_map() -> map(),
array_reduce() -> foldl() ("fold left")
?>
函数式编程是一种范式,它围绕函数的无副作用评估展开。程序执行是调用函数,而函数又可能由许多其他函数定义。一个想法是使用函数从其他函数创建特殊用途的函数。
上面提到的数组函数允许您对数组组合新函数。
例如,array_sum = array_map("sum", $arr)。
这导致了一种看起来非常像代数的编程风格,例如 Bird/Meertens 形式主义。
例如,数学家可能会说
map(f o g) = map(f) o map(g)
即所谓的“循环融合”定律。
许多数组函数可以通过使用 foldr() 函数创建(其工作原理类似于 foldl,但从右侧吞噬数组元素)。
我在这里无法详细说明,我只是想提供一个关于这些东西出现在哪里以及其背后的理论的提示。
我最喜欢使用此函数的方法是将字符串转换为数组,修剪每一行并删除空行
<?php
$array = array_filter(array_map('trim', explode("\n", $string)), 'strlen');
?>
虽然它清楚地说明了数组键被保留,但重要的是要注意这包括按数字索引的数组。您不能在上面的 $array 上使用 for 循环,除非先通过 array_values() 处理它。
根据您的“空”数组值的预期含义,例如 null 和空字符串,与整数 0 或布尔值 false 相比,请注意不同过滤器产生的结果。
<?php
declare(strict_types=1);
$array = array( 'null' => null, 'nullstring' => '', 'intzero' => 0, 'stringzero' => '0', 'false' => false, 'stringfalse' => 'false', );
// 删除 null、null 字符串 - 但也删除 FALSE!
$filtered1 = array_filter( $array, 'strlen' );
// 只删除 null。
$filtered2 = array_filter( $array, function( $v ) { return !is_null( $v ); } );
// 删除 null 和 null 字符串。保留 FALSE 和 0。
$filtered3 = array_filter( $array, function( $v ) { return !( is_null( $v) or '' === $v ); } );
var_dump( $array, $filtered1, $filtered2, $filtered3 );
?>
结果为
array (size=3)
'intzero' => int 0
'stringzero' => string '0' (length=1)
'stringfalse' => string 'false' (length=5)
array (size=5)
'nullstring' => string '' (length=0)
'intzero' => int 0
'stringzero' => string '0' (length=1)
'false' => boolean false
'stringfalse' => string 'false' (length=5)
array (size=4)
'intzero' => int 0
'stringzero' => string '0' (length=1)
'false' => boolean false
'stringfalse' => string 'false' (length=5)
上面的文档或任何注释中都没有提到,但如果您的匿名函数需要来自外部的变量,则必须使用 "use" 关键字,否则它将无法工作。
示例 1
<?php
$people = [
[
'id' => 23,
'name' => 'John',
'lastname' => 'Williams',
],
[
'id' => 56,
'name' => 'Hans',
'lastname' => 'Zimmer',
],
];
function filter_by_name ($name) {
global $people;
$filtered = array_filter($people, function($n) use($name) {
return $n['name'] == $name;
});
return $filtered;
}
print_r (filter_by_name ('John'));
?>
示例 2,使用多个变量
<?php
$people = [
[
'id' => 23,
'name' => 'John',
'lastname' => 'Williams',
],
[
'id' => 56,
'name' => 'Hans',
'lastname' => 'Zimmer',
],
];
function filter_array_by_column ($array, $column, $value) {
$filtered = array_filter($array, function($row) use($column, $value) {
return $row[$column] == $value;
});
return $filtered;
}
print_r (filter_array_by_column ($people, 'name', 'John'));
?>
检查数组中所有元素是否非空/null/假值。
------------------------------
假设您有一个一维数组...
<?php
$spicy_numbers = [69, 420, ɸ];
?>
您想要轻松地检查该数组中所有元素是否不为 null/empty/任何假值,而不是对每个元素运行循环,您可以将该数组传递给 <?php array_filter() ?>,不带回调函数,然后检查返回的数组是否与原始数组大小相同,因为 <?php array_filter() ?> 在没有提供回调函数的情况下会去除所有非真值,包括 0。
示例
<?php
$spicy_numbers = [69, 420, '']; // Phi is gone!
if ( count( array_filter( $spicy_numbers ) ) !== count( $spicy_numbers ) ) {
// 其中一个元素为空/null/假值。
} else {
// 所有元素都存在且为真值。
}
?>
您可以将此写成一个简洁的小函数
<?php
/**
* 检查给定数组的所有元素是否具有非假值。
* 用例:如果数组中的所有项目都已设置并具有值(当然为真值),则执行 X;否则,执行 Y。
*
* @param array $arr
* @return bool
*/
function is_array_full( $arr ) {
$array_count = count( $arr );
$filtered_count = count( array_filter( $arr ) );
return ( $array_count === $filtered_count ) ? true : false;
}
?>