PHP 中刪除數組元素最常用 unset() 和 array_splice(),但兩者在索引重排、返回值、性能、適用場景上有本質區別。本文深度對比並給出選型決策樹。
unset() | array_splice() |
|------|---------------------|----------------------------|
| **索引重排** | ❌ 保留原鍵,產生「稀疏數組」 | ✅ 重置數字索引 (0,1,2...) |
| **返回值** | void | 被刪除元素組成的新數組 |
| **操作對象** | 按鍵名刪除 | 按偏移量/長度刪除 |
| **關聯數組** | 完美支持 | 僅重置數字鍵,字符串鍵保留 |
| **性能** | O(1) 極快 | O(n) 需移動後續元素 |
| **原地修改** | ✅ | ✅ |
<?php
$arr = ['a', 'b', 'c', 'd']; // 索引: 0,1,2,3
unset($arr[1]);
var_dump($arr);
/* 輸出:
array(3) {
[0]=> string(1) "a"
[2]=> string(1) "c" // 索引 1 消失,變稀疏
[3]=> string(1) "d"
}
*/
// 關聯數組完美支持
$assoc = ['x' => 1, 'y' => 2, 'z' => 3];
unset($assoc['y']);
// ['x' => 1, 'z' => 3] 鍵完整保留
<?php
$arr = ['a', 'b', 'c', 'd'];
$removed = array_splice($arr, 1, 1); // 從偏移 1 刪除 1 個
var_dump($removed); // array(1) { [0]=> "b" }
var_dump($arr);
/* 輸出:
array(3) {
[0]=> "a"
[1]=> "c" // 索引重排:0,1,2
[2]=> "d"
}
*/
// 關聯數組:字符串鍵保留,數字鍵重排
$assoc = ['x' => 1, 'y' => 2, 'z' => 3];
array_splice($assoc, 1, 1); // 偏移 1 刪除 1 個
// 結果:['x' => 1, 'z' => 3] — 字符串鍵未變,但順序改變
<?php
$arr = [10, 20, 30, 40, 50];
$valueToRemove = 30;
// unset 版
$key = array_search($valueToRemove, $arr);
if ($key !== false) unset($arr[$key]);
// 結果:[0=>10, 1=>20, 3=>40, 4=>50] 稀疏
// array_splice 版
$key = array_search($valueToRemove, $arr);
if ($key !== false) array_splice($arr, $key, 1);
// 結果:[0=>10, 1=>20, 2=>40, 3=>50] 緊湊
// 批量刪除特定值
$arr = [1, 2, 3, 2, 4, 2, 5];
$arr = array_values(array_filter($arr, fn($v) => $v !== 2));
// [1, 3, 4, 5] — 一行搞定,推薦
<?php
$arr = ['a','b','c','d','e','f'];
// unset: 需循環
foreach (range(1, 3) as $i) unset($arr[$i]);
// 結果:[0=>'a', 4=>'e', 5=>'f']
// array_splice: 一行
array_splice($arr, 1, 3); // 偏移1,長度3
// 結果:[0=>'a', 1=>'e', 2=>'f']
<?php
$arr = [1, 2, 3, 4, 5];
array_splice($arr, 2, 1, ['x', 'y']); // 索引2刪1個,插入x,y
// 結果:[1, 2, 'x', 'y', 4, 5]
<?php
$arr = range(1, 100000);
// unset
$start = microtime(true);
unset($arr[50000]);
echo "unset: " . (microtime(true) - $start) * 1000 . " ms\n";
// ~0.001 ms
// array_splice
$arr = range(1, 100000);
$start = microtime(true);
array_splice($arr, 50000, 1);
echo "array_splice: " . (microtime(true) - $start) * 1000 . " ms\n";
// ~2.5 ms (需移動 5萬個元素)
// array_filter 重建 (按值刪除)
$arr = range(1, 100000);
$start = microtime(true);
$arr = array_values(array_filter($arr, fn($v) => $v !== 50000));
echo "array_filter: " . (microtime(true) - $start) * 1000 . " ms\n";
// ~3.5 ms
unset():O(1),極快,適合高頻、大數據、按鍵刪除array_splice():O(n),需移動內存,適合需索引緊湊、區間刪除、刪除並插入array_filter() + array_values():O(n),全量重建,適合按值過濾、函數式風格<?php
/**
* 統一數組刪除函數
* @param array $array 目標數組 (引用)
* @param int|string|callable $criteria 鍵名/偏移量/回調函數
* @param int $length 刪除長度 (僅 array_splice 模式)
* @param bool $reindex 是否重排索引
* @param array $replacement 替換元素 (僅 array_splice)
* @return array 被刪除的元素
*/
function array_delete(
array &$array,
int|string|callable $criteria,
int $length = 1,
bool $reindex = true,
array $replacement = []
): array {
if (is_callable($criteria)) {
// 按值/條件刪除
$removed = [];
$array = array_values(array_filter($array, function($v, $k) use ($criteria, &$removed) {
$match = $criteria($v, $k);
if ($match) $removed[] = $v;
return !$match;
}, ARRAY_FILTER_USE_BOTH));
return $removed;
}
if (is_string($criteria)) {
// 關聯數組按鍵名
if (!array_key_exists($criteria, $array)) return [];
$removed = [$array[$criteria]];
unset($array[$criteria]);
if ($reindex) $array = array_values($array);
return $removed;
}
// 數字索引/偏移量
if ($criteria < 0) $criteria = max(0, count($array) + $criteria);
if ($criteria >= count($array)) return [];
if ($reindex || $replacement) {
return array_splice($array, $criteria, $length, $replacement);
} else {
$removed = array_slice($array, $criteria, $length);
foreach (range($criteria, $criteria + $length - 1) as $i) {
unset($array[$i]);
}
return $removed;
}
}
// 使用示例
$arr = ['a','b','c','d','e'];
array_delete($arr, 1); // 刪除索引1,重排
array_delete($arr, 'key'); // 關聯鍵刪除
array_delete($arr, fn($v) => $v > 'c'); // 條件刪除
array_delete($arr, 1, 2, true, ['x']); // 區間刪除並插入
<?php
$arr = ['a' => 'abc', 'b' => '', 'c' => 'def', 'd' => null, 'e' => 0, 'f' => false];
// 刪除空字符串、null、false、0 (所有假值)
$filtered = array_filter($arr); // 不帶回調默認過濾假值
// ['a' => 'abc', 'c' => 'def']
// 保留 0 和 false,只刪空字符串和 null
$filtered = array_filter($arr, fn($v) => $v !== '' && $v !== null);
// ['a' => 'abc', 'c' => 'def', 'e' => 0, 'f' => false]
unset($arr[$key])array_splice($arr, $offset, $len, $replacement)array_values(array_filter($arr, $callback))unset($arr['key']) (最語義化、最快)array_delete() 工具函數,統一團隊風格理解底層差異,根據場景選擇正確工具,是從「能跑通」進化為「高性能、可維護」的關鍵一步。