要按键删除 PHP 数组中的元素,使用 unset($array[$key])。元素被删除后,其他键保持原样不变,而且 unset 一个不存在的键也不会报错。
看看第二个结果:键现在是 0, 2, 3。unset 从不重新编号。
unset 之后重建数组索引
键中有空缺的列表以后会带来麻烦:for ($i = 0; ...) 循环会碰到缺失的索引,json_encode 会输出一个 JSON 对象而不是数组。array_values() 能让键重新变得整齐。
用 array_splice 按位置删除
array_splice($array, $offset, $length) 从位置 $offset 开始删除 $length 个元素,重新编号键,并返回被删除的元素。负的偏移量从末尾开始计数。它还可以在同一次调用中插入替换元素。
array_splice 作用于位置,而不是键:对关联数组,它按元素在顺序中的位置删除,并保留字符串键。array_slice 页面把它和 array_slice 做了比较,后者只复制一部分,不修改原数组。
按值删除元素
array_diff($array, [$value]) 返回去掉所有等于 $value 的元素之后的数组,其余元素的键保持不变。只删除第一个匹配时,先用 array_search 找到它的键,再 unset。
array_diff 把值当作字符串比较,所以 array_diff([1, "1", 2], [1]) 会同时删除整数和字符串。当条件不只是“等于某个值”时,使用带回调的 array_filter。
删除第一个或最后一个元素
array_shift() 删除第一个元素,array_pop() 删除最后一个元素。两者都返回被删除的元素,用来实现队列和栈很方便。
array_shift 会把数字键从 0 开始重新编号。array_pop 不需要这样做,因为空缺在末尾。
一次删除多个键
unset 可以在一次调用中删除多个元素。如果要删除的键名放在一个数组里,先用 array_flip() 翻转它,让键名变成键,再传给 array_diff_key()。
常见错误:值不存在时用 array_search 配合 unset
array_search 什么都没找到时返回 false,而 false 用作数组键时会变成 0。所以只要值不在数组中,下面这行就会删除第一个元素:
一定要先保存 array_search 的结果,用 !== false 比较之后再把它当作键使用。单纯写 if ($key) 也不够:在索引 0 处找到的匹配同样是假值。
常见问题
PHP 中怎么根据值删除数组元素?
要删除所有出现的该值,使用 array_diff($arr, ['value'])。只删除第一个时,先找到它的键再 unset,同时检查是否找到:$k = array_search('value', $arr); if ($k !== false) { unset($arr[$k]); }。
unset 之后怎么重建数组索引?
用 array_values() 包一下:$arr = array_values($arr); 会把键从 0 开始重新编号。也可以直接用 array_splice($arr, $index, 1) 删除元素,它会自动重新编号。
怎么删除数组的第一个或最后一个元素?
array_shift($arr) 删除并返回第一个元素,同时重新编号数字键。array_pop($arr) 删除并返回最后一个元素。
可以在 foreach 循环中 unset 元素吗?
可以。foreach ($arr as $k => $v) { if ($v < 0) { unset($arr[$k]); } } 是安全的,因为 foreach 遍历的是数组的副本,而你修改的是原数组。键会保留空缺,所以如果需要一个列表,之后调用 array_values()。
unset 一个不存在的键会报错吗?
不会。unset($arr['missing']) 什么也不做,也不会产生警告,所以不需要先用 isset 检查。