在日常的PHP 編程中, array_diff()是一個非常實用的函數,它可以用來找出兩個數組之間的差異。但很多開發者在使用這個函數時可能會遇到一種奇怪的情況:
這到底是怎麼回事呢?讓我們一起來探究其中的原因。
來看下面這段代碼:
$a = [true, false];
$b = [0];
$result = array_diff($a, $b);
print_r($result);
你可能會直覺地認為true和false都不在數組$b中,所以$result應該是[true, false] ,但實際上你會得到如下輸出:
Array
(
[0] => 1
)
是不是有點懵?為什麼false被過濾掉了?而且true還變成了整數1 ?我們接下來逐步拆解這個問題。
首先要理解array_diff()的底層行為。根據PHP 官方文檔的說明:
array_diff() 使用“非嚴格比較”(==)來檢查值是否相等。
也就是說, array_diff()並不是使用全等===來比較值,而是用雙等號== 。
這就意味著以下值會被認為是“相等”的:
false == 0; // true
true == 1; // true
true == "1"; // true
false == ""; // true
在我們的示例中, false被0判定為相等,因此被array_diff()排除在結果之外。
另一個細節是, array_diff()返回的數組是數值數組,PHP 會在某些情況下對布爾值進行隱式轉換。例如:
var_dump(true); // 輸出 bool(true)
echo true; // 輸出 1
在print_r()中輸出時,布爾值true會被轉換為1 。這就是為什麼你會看到結果中出現了1 ,而不是true 。
如果你需要比較的數據類型比較嚴格(比如你真的需要區分true和1 ),可以使用array_udiff()並配合一個自定義的比較函數:
$a = [true, false];
$b = [0];
$result = array_udiff($a, $b, function($x, $y) {
return ($x === $y) ? 0 : 1;
});
print_r($result);
輸出:
Array
(
[0] => 1
[1] =>
)
注意,這次false (對應值為空)也被保留了,因為我們使用了全等比較=== 。
如果你需要更清晰地區分這些值並保留布爾類型的表現形式,可以結合var_export()來輸出結果:
var_export($result);
array_diff()的默認行為雖然在很多場景下表現得非常高效,但在處理布爾值、數字與字符串混合的數組時,就容易產生讓人疑惑的結果。這也是PHP 中類型弱化帶來的一個典型陷阱。
在開發中,如果你對數據類型有嚴格要求,避免使用默認的array_diff() ,轉而使用array_udiff()並提供自己的比較函數,是一個更安全可靠的做法。