unset() 刪除陣列元素後,不會自動重建數字索引,這是最常見的坑:
$a = ['a1', 'a2', 'a3']; // 索引 0,1,2
unset($a[0]); // 刪除第一個
// 錯誤做法:for 迴圈配合 count()
for ($i = 0; $i < count($a); $i++) {
echo $a[$i] . ' '; // 索引 0 為空,輸出: a2 a3 (但 $i=2 時 $a[2] 不存在)
}
// 正確做法 1:foreach(操作副本,不受影響)
foreach ($a as $val) {
echo $val . ' '; // a2 a3
}
// 正確做法 2:while + each() 配合 reset()(舊式)
reset($a);
while (list($key, $val) = each($a)) {
echo $val . ' '; // a2 a3
}
// 正確做法 3:array_values() 重建索引
$a = array_values($a); // 索引重建為 0,1
for ($i = 0; $i < count($a); $i++) { ... }
PHP 字串可像陣列用 $str[$i] 存取單字元,比 substr() 快:
$str = "something";
// 慢:每次呼叫 substr()
for ($i = 0; $i < strlen($str); $i++) {
$ch = substr($str, $i, 1);
}
// 快:直接陣列存取
for ($i = 0; $i < strlen($str); $i++) {
$ch = $str[$i];
}
// 更快:foreach 遍歷字元(PHP 7+)
foreach (str_split($str) as $ch) { ... }
$data = [1, 2, 3, 4, 5, 6];
// 保留偶數
$filtered = array_filter($data, fn($v) => $v % 2 === 0);
// [2, 4, 6] 索引保留原鍵名
// 需重建索引
$filtered = array_values(array_filter($data, fn($v) => $v % 2 === 0));
// [0=>2, 1=>4, 2=>6]
$data = [1, 2, 3, 4, 5, 6];
// 從後往前刪,不影響前面索引
for ($i = count($data) - 1; $i >= 0; $i--) {
if ($data[$i] % 2 !== 0) {
unset($data[$i]);
}
}
// 結果:[1=>2, 3=>4, 5=>6] 索引斷層
$data = array_values($data); // 重建
$to_delete = [];
foreach ($data as $key => $val) {
if ($val % 2 !== 0) {
$to_delete[] = $key;
}
}
foreach ($to_delete as $key) {
unset($data[$key]);
}
function array_deep_remove(array &$arr, callable $condition): void {
foreach ($arr as $key => $value) {
if (is_array($value)) {
array_deep_remove($arr[$key], $condition);
if (empty($arr[$key])) {
unset($arr[$key]);
}
} elseif ($condition($value, $key)) {
unset($arr[$key]);
}
}
}
$data = [
'users' => [
['id' => 1, 'active' => true],
['id' => 2, 'active' => false],
],
'settings' => [
'theme' => 'dark',
'debug' => false,
]
];
// 刪除 inactive 用戶與 debug 設定
array_deep_remove($data, fn($v, $k) =>
($k === 'active' && $v === false) ||
($k === 'debug' && $v === false)
);
| 方法 | 相對耗時 | 記憶體 | 適用場景 |
|---|---|---|---|
| array_filter + array_values | 1.0x (基準) | 雙倍(建新陣列) | 一般情況首選,語意清晰 |
| 反向 for + unset | 0.7x | 原地修改 | 極大陣列、記憶體敏感 |
| foreach 收集鍵再 unset | 1.2x | 額外鍵陣列 | 條件複雜、需記錄刪除項 |