unset() 是 PHP 中刪除變數或陣列元素的核心函數,但其「不重建索引」的特性常導致後續 foreach 遍歷、索引存取出現邏輯錯誤。本文詳細解析 unset() 行為,並提供 array_values()、array_splice() 等重建索引的最佳方案。
當使用 unset($arr[$key]) 刪除陣列元素時,PHP 僅移除該鍵值對,不會自動重新排序數字索引。這意味著陣列會出現「索引斷層」。
<?php
$arr = ['朝陽區', '海澱區', '西城區', '東城區', '豐台區'];
// 索引: 0, 1, 2, 3, 4
unset($arr[3]); // 刪除 '東城區'
print_r($arr);
?>
輸出結果:
Array
(
[0] => 朝陽區
[1] => 海澱區
[2] => 西城區
[4] => 豐台區 // 索引 3 消失,直接跳到 4
)
<?php
echo $arr[3]; // Notice: Undefined offset: 3
?>
<?php
count($arr); // 返回 4
// 但最大索引為 4,若用 for 迴圈 $i < count($arr) 會漏掉 $arr[4]
?>
<?php
json_encode($arr);
// 輸出: {"0":"朝陽區","1":"海澱區","2":"西城區","4":"豐台區"}
// 前端 JS 解析時 length 為 5,索引 3 為 undefined
?>
<?php
$arr = array_values($arr);
// 結果: [0=>'朝陽區', 1=>'海澱區', 2=>'西城區', 3=>'豐台區']
?>
<?php
// 刪除索引 3 並自動重建
array_splice($arr, 3, 1);
// 等同於: unset($arr[3]); $arr = array_values($arr);
?>
<?php
$newArr = [];
foreach ($arr as $k => $v) {
if ($k !== 3) $newArr[$k] = $v; // 保留原鍵名
}
?>
| 方法 | 時間複雜度 | 記憶體 | 適用場景 |
|---|---|---|---|
unset() + array_values() | O(n) | 建立新陣列 | 通用、陣列較小 |
array_splice() | O(n) | 原地修改 | 大陣列、連續刪除 |
foreach 重建 | O(n) | 建立新陣列 | 需保留關聯鍵名 |
array_values()foreach 或 array_filter() 避免索引斷層問題json_encode() 前確保索引連續,或用 array_values() 強制轉列表理解 unset()「不重建索引」的設計初衷(效能考量),並掌握對應的重建策略,能有效避免陣列操作中的隱性 Bug,寫出更健壯的 PHP 程式碼。