如果您想要快速移除 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_values() 函式重新索引結果 陣列。
array
要迭代的陣列
callback
要使用的回呼函式
如果沒有提供 callback
,則 array
中所有空項目將會被移除。關於 PHP 如何定義空項目,請參考 empty()。
mode
決定傳遞給 callback
的參數的旗標
ARRAY_FILTER_USE_KEY
- 將鍵值作為唯一參數傳遞給 callback
,而不是值
ARRAY_FILTER_USE_BOTH
- 將值和鍵值作為參數傳遞給 callback
,而不是只有值
0
,這會將值作為唯一參數傳遞給 callback
。
回傳過濾後的陣列。
版本 | 說明 |
---|---|
8.0.0 |
callback 現在可以為 null。 |
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"]
如果您像我一樣,因為使用了位元運算子 (&) 而難以理解範例 #1,以下說明。
有問題的部分是這個回呼函式
<?php
function odd($var)
{
// 傳回輸入的整數是否為奇數
return($var & 1);
}
?>
如果給定一個整數,如果 $var 為奇數,此函式會傳回整數 1,如果 $var 為偶數,則傳回整數 0。
單個「&」符號 (&) 是位元 AND 運算子。它的運作方式是採用兩個參數的二進位表示法,並使用 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() ("由左摺疊")
?>
函數式程式設計是一種以無副作用的函式求值為中心的範式。程式執行是函式的呼叫,而函式又可能由許多其他函式定義。一個想法是使用函式從其他函式創建特殊用途的函式。
上面提到的陣列函式允許您在陣列上組合新的函式。
例如,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 和空字串 -- 但也會移除 FALSE!
$filtered1 = array_filter( $array, 'strlen' );
// 只移除 null。
$filtered2 = array_filter( $array, function( $v ) { return !is_null( $v ); } );
// 移除 null 和空字串。保留 FALSE 和 0。
$filtered3 = array_filter( $array, function( $v ) { return !( is_null( $v) or '' === $v ); } );
var_dump( $array, $filtered1, $filtered2, $filtered3 );
?>
結果:
陣列 (大小=3)
'intzero' => int 0
'stringzero' => 字串 '0' (長度=1)
'stringfalse' => 字串 'false' (長度=5)
陣列 (大小=5)
'nullstring' => 字串 '' (長度=0)
'intzero' => int 0
'stringzero' => 字串 '0' (長度=1)
'false' => 布林值 false
'stringfalse' => 字串 'false' (長度=5)
陣列 (大小=4)
'intzero' => int 0
'stringzero' => 字串 '0' (長度=1)
'false' => 布林值 false
'stringfalse' => 字串 'false' (長度=5)
檢查陣列中所有元素是否不為空/null/假值。
------------------------------
假設你有一個一維陣列...
<?php
$spicy_numbers = [69, 420, ɸ];
?>
而且你想要輕鬆地檢查該陣列中的所有元素是否不為 null/空/任何假值,而不是對每個元素執行迴圈,你可以將陣列傳遞給 <?php array_filter() ?>,不帶回呼函式,然後檢查返回的陣列是否與原始陣列大小相同,因為當沒有提供回呼函式時,<?php array_filter() ?> 會去除所有非真值,包括 0。
範例
<?php
$spicy_numbers = [69, 420, '']; // Phi 不見了!
if ( count( array_filter( $spicy_numbers ) ) !== count( $spicy_numbers ) ) {
// 其中一個元素是空的/null/false。
} else {
// 所有元素都存在且為 true。
}
?>
您可以將它寫成一個簡潔的小函式:
<?php
/**
* 檢查給定陣列的所有元素是否都具有非 false 的值。
* 使用案例:如果陣列中的所有項目都已設定且具有值(當然是 true),則執行 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;
}
?>