PHP: How do you delete an array element by its value?
unset($array[$key]) assumes you know the key. Often you only know the value,
though. Then you have to look up the key first — and there is one line in that
which is easy to get wrong.
Removing one occurrence
<?php
$key = array_search('green', $colours, true);
if ($key !== false) {
unset($colours[$key]);
}
?>
array_search() returns the key of the first match, or false if the value
does not occur.
As described in article 0005, unset() leaves a gap in the keys:
array_search('green', $a, true) : 1
afterwards : ["red","blue"] keys=[0,2]
If you need consecutive keys — because the array is meant to go out as a JSON
array, for instance — append an array_values().
The line people get wrong
The !== false is not decoration. If you write plain if ($key) instead, the
code works for every element except the first:
index of 'red' : 0
if ($i) : false <- the match is missed!
if ($i !== false) : true
array_search() returns key 0 for the first element, and 0 is falsy. The
element is found and still not deleted. It is a bug that tends to be missed in
tests, because you rarely test with the first element.
Incidentally the same goes for associative arrays with a key like '0' — PHP
turns that into an integer internally.
The third parameter
The third parameter of array_search() switches to strict comparison. Without
it PHP compares loosely, and then the search finds things you did not mean:
array_search('1', [1,2,3]) : 0 <- the string matches the integer
array_search('1', [1,2,3], true) : false
array_search(0, [null,'x']) : 0 <- null == 0
array_search(0, [null,'x'], true) : false
The second case is the nasty one. You search for the number 0 and delete a
null. With data from a database, where null occurs regularly, that is a bug
which stays unnoticed for a long time.
My recommendation: always set the third parameter to true. If you genuinely
want a loose comparison, write a comment about it.
Removing all occurrences
array_search() only finds the first match. If the value occurs several times,
you need something else.
array_filter() with a condition of your own:
<?php
$withoutA = array_filter($values, fn($v) => $v !== 'a');
?>
array_filter : ["b","c"] keys=[1,3]
array_diff() is shorter and can take several values at once:
<?php
$withoutA = array_diff($values, ['a']);
$withoutAC = array_diff($values, ['a', 'c']);
?>
array_diff($e, ['a']) : ["b","c"] keys=[1,3]
several at once : ["b"]
Both preserve the keys, so both leave gaps.
Why I do not recommend array_diff() everywhere
array_diff() has one property you need to know about: it compares the values
as strings. The manual says so too, it is just that people rarely look it
up.
array_diff([0,1,2,'0'], [false]) : [0,1,2,"0"] <- nothing removed
array_diff([0,1,2], ['0']) : [1,2] <- the 0 is gone
In the first line false becomes '', and that is none of the elements — so
nothing happens. In the second line '0' becomes '0' and thereby matches the
integer 0.
So as soon as null, false or mixed types are in the array, array_diff()
is the wrong choice. array_filter() with !== compares strictly and does
exactly what it says. With pure string arrays — tags, names, IDs as text — you
can use array_diff() without hesitation.
Associative arrays
With an associative array you specifically do not want array_values(),
because it destroys your keys:
<?php
$withoutOne = array_filter($config, fn($v) => $v !== 1);
?>
array_filter : {"b":2}
The keys are preserved, and here that is exactly right.
Summary
- One occurrence:
array_search()+unset(), checked with!== false. - The
!== falseis mandatory, otherwise the code fails on the first element. - Set the third parameter of
array_search()totrue— otherwise a search for0also matches anull. - All occurrences:
array_filter()with!==, orarray_diff(). array_diff()compares as strings; withnull,falseor mixed types preferarray_filter().array_values()only for lists, not for associative arrays.
About Netcup (advertisement)
The German host Netcup offers, among other things, affordable and powerful web hosting packages, KVM-based root servers and dedicated servers. With our voucher codes you can save even more (6€ off your first order, 30% off all KVM-based root servers, ...).