# removing an item from an array

- Thread: https://externals.io/message/62201
- Original archive: https://news-web.php.net/php.internals/62201
- Started by Rasmus Schultz on 2012-08-15T20:18:21+00:00
- Messages: 15
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #62201 — Rasmus Schultz — 2012-08-15T20:18:21+00:00

URL: https://externals.io/message/62201#62201

How come there is no straight-foward obvious way to simply remove a given
value from an array?

Just look at the number of horrible ways people solve this obvious problem:

http://stackoverflow.com/questions/7225070/php-array-delete-by-value-not-key

Shouldn't we have something simple, like:

    array_remove($array, $value) : array (returns a new array)

and/or

    array_delete(&$array, $value) : bool (modifies array directly)

?

---

## #62202 — Stas Malyshev — 2012-08-15T20:22:19+00:00

URL: https://externals.io/message/62201#62202 · In reply to: #62201

Hi!

> How come there is no straight-foward obvious way to simply remove a given
> value from an array?

The same reason there's no simple way to undefine variable whose value
is 42 without knowing the variable name. Array is a container indexed by
keys, not values. So if you've got just a value, there's no way to know
if it's in the container at all, and if it is, where it is, except for
going through all the values and checking if any of them is equal to
what you nedd.

> Just look at the number of horrible ways people solve this obvious problem:

I see:
if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

Nothing horrible here.

-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #62203 — Will Fitch — 2012-08-15T20:23:57+00:00

URL: https://externals.io/message/62201#62203 · In reply to: #62202

I like that chose 42 for the value.  You win, and I completely agree.

On Wed, Aug 15, 2012 at 4:22 PM, Stas Malyshev <smalyshev@sugarcrm.com>wrote:

> Hi!
>
> > […]
>
> The same reason there's no simple way to undefine variable whose value
> is 42 without knowing the variable name. Array is a container indexed by
> keys, not values. So if you've got just a value, there's no way to know
> if it's in the container at all, and if it is, where it is, except for
> going through all the values and checking if any of them is equal to
> what you nedd.
>
> > […]
> problem:
>
> I see:
> if(($key = array_search($del_val, $messages)) !== false) {
>     unset($messages[$key]);
> }
>
> Nothing horrible here.
>
> --
> Stanislav Malyshev, Software Architect
> SugarCRM: http://www.sugarcrm.com/
> (408)454-6900 ext. 227

---

## #62204 — Nikita Popov — 2012-08-15T20:27:22+00:00

URL: https://externals.io/message/62201#62204 · In reply to: #62202

> Hi!
>
> > […]
>
> The same reason there's no simple way to undefine variable whose value
> is 42 without knowing the variable name. Array is a container indexed by
> keys, not values. So if you've got just a value, there's no way to know
> if it's in the container at all, and if it is, where it is, except for
> going through all the values and checking if any of them is equal to
> what you nedd.
>
> > […]
>
> I see:
> if(($key = array_search($del_val, $messages)) !== false) {
>     unset($messages[$key]);
> }
>
> Nothing horrible here.

In addition to that, one should be aware that a value can exist
multiple times in an array, whereas keys are unique. So there are
infinitely many possible deletion strategies.

Btw, deleting all values (not just the first) is also very easy currently:

foreach (array_keys($array, $delValue) as $key) {
    unset($array[$key]);
}

---

## #62205 — Kris Craig — 2012-08-15T20:29:47+00:00

URL: https://externals.io/message/62201#62205 · In reply to: #62204

>
>
> Btw, deleting all values (not just the first) is also very easy currently:
>
> foreach (array_keys($array, $delValue) as $key) {
>     unset($array[$key]);
> }
>
>
Even easier still, just do this:

$array_var = array();

--Kris

---

## #62206 — Nikita Popov — 2012-08-15T20:31:20+00:00

URL: https://externals.io/message/62201#62206 · In reply to: #62205

> > […]
>
> Even easier still, just do this:
>
> $array_var = array();

It's often overlooked, but array_keys has a second parameter that only
returns the keys for a certain value: http://php.net/array_keys ;) So
no, that does not clean off the whole array.

Nikita

---

## #62207 — Kris Craig — 2012-08-15T20:35:55+00:00

URL: https://externals.io/message/62201#62207 · In reply to: #62206

> 
> > […]
> currently:
> > […]
>
> It's often overlooked, but array_keys has a second parameter that only
> returns the keys for a certain value: http://php.net/array_keys ;) So
> no, that does not clean off the whole array.
>
> Nikita
>

If you re-initialize it by setting it to array(), then yes that most
definitely will clear all the values in the array.  As far as I know,
 `array_keys()` has nothing to do with that.

--Kris

---

## #62208 — Kris Craig — 2012-08-15T20:37:53+00:00

URL: https://externals.io/message/62201#62208 · In reply to: #62207

>
>
> On Wed, Aug 15, 2012 at 1:31 PM, Nikita Popov <nikita.ppv@gmail.com>wrote:
>
> > […]
>
> If you re-initialize it by setting it to array(), then yes that most
> definitely will clear all the values in the array.  As far as I know,
> `array_keys()` has nothing to do with that.
>
> --Kris
>
>
Err nevermind, I think I misread what you were trying to do.  If you want
to only clear a certain value, then yes using `array_keys()` with a search
value specified is the way to go.  If you want to clear all values in the
array period (which is what I thought you were saying), then
re-initializing with array() makes the most sense.

--Kris

---

## #62211 — Lars Schultz — 2012-08-16T05:40:20+00:00

URL: https://externals.io/message/62201#62211 · In reply to: #62202

Am 15.08.2012 22:22, schrieb Stas Malyshev:
> > […]
>
> I see:
> if(($key = array_search($del_val, $messages)) !== false) {
>      unset($messages[$key]);
> }
>
> Nothing horrible here.
>
One thing that should be noted in this case and any solution that relies 
on unset() is that even though its simple and fast, it will not result 
in a properly indexed array. The same goes for any array_diff based 
solution.

I tried and compared the following solutions and ordered them according 
to their performance. The fastest (and with a correct result) solution 
is based on array_slice. Why this is the case I can not say...I am not 
arguing for another array-function (as there are so many already)...but 
I certainly have my own array_remove implementation, since it's such a 
common use-case.

function array_remove_slice(&$haystack,$needle){
	while ( true ) {
		$pos = array_search($needle,$haystack,true);
		if ( $pos === false ) return;
		
		$haystack = array_merge(
			array_slice($haystack,0,$pos) ,
			array_slice($haystack,$pos+1)
		);
	}
}

/* ~1.5 times slower than slice */
function array_remove_unset(&$haystack,$needle){
	while ( true ) {
		$pos = array_search($needle,$haystack,true);
		if ( $pos === false ) break;
		
		unset($haystack[$pos]);
	}
}

/* ~2.3 times slower than slice */
function array_remove_loop(&$haystack,$needle){
	$result = array();
	foreach( $haystack as $value ) {
		if ( $needle == $value ) continue;
		$result[] = $value;
	}
	$haystack = $result;
}


/* ~3.5 times slower than slice */
function array_remove_diff(&$haystack,$needle){
	$haystack = array_diff($haystack,array($needle));
}

---

## #62234 — Alexey Zakhlestin — 2012-08-18T06:42:08+00:00

URL: https://externals.io/message/62201#62234 · In reply to: #62201

> How come there is no straight-foward obvious way to simply remove a given
> value from an array?

Well, this sounds like a reason for creating SplSet class

---

## #62245 — Levi Morrison — 2012-08-18T16:08:16+00:00

URL: https://externals.io/message/62201#62245 · In reply to: #62234

>
> 
>
> > […]
>
> Well, this sounds like a reason for creating SplSet class
>

There's already SplObjectStorage which CAN act like a Set for objects
only.  It's a terrible solution in my opinion and am working on
creating a proper one.  I don't know if that effort will be accepted,
but I wanted to point out that a set already exists in the SPL.

---

## #62289 — Rasmus Schultz — 2012-08-20T15:35:00+00:00

URL: https://externals.io/message/62201#62289 · In reply to: #62234

I think adding more collection-types is the intuitive reaction to this
issue, but there's something to be said for the idea of having only a
single collection-type - I think that's one PHP feature we should not give
up.

Not having to pick and choose (and compromise) to select the "right"
collection-type, and not having to refactor when you realize you needed
another collection-type - as well as easy comprehension for developers...
these are valuable aspects of having only a single collection-type. Some
newer languages like Opa embrace that idea with great elegance. Giving up
on that idea should be the last option, in my opinion.

There are plenty of cases for collections of objects that do not have a
scalar key, where the key is indeterminate, or where the key can change -
and thus cannot have known indexes.

As an aside note, I recently benchmarked `array_search()` for a project that
needs to store many different types of objects in a list - and searching a
list with 1000 objects for one specific object is extremely fast: a couple
of micro-seconds more (per search) when compared against a hash-based
lookup with a known key, so (in my case) nothing to worry about at all in
terms of performance.

Arrays are a powerful and pure feature in PHP - I would vote against
introducing more collection-types, and instead leverage the already
powerful and well-understood existing singular collection-type.


On Sat, Aug 18, 2012 at 2:42 AM, Alexey Zakhlestin <indeyets@gmail.com>wrote:

>
> 
>
> > […]
>
> Well, this sounds like a reason for creating SplSet class

---

## #62382 — Yasuo Ohgaki — 2012-08-22T01:45:59+00:00

URL: https://externals.io/message/62201#62382 · In reply to: #62201

Hi,

2012/8/16 Rasmus Schultz <rasmus@mindplay.dk>:
> How come there is no straight-foward obvious way to simply remove a given
> value from an array?
>
> Just look at the number of horrible ways people solve this obvious problem:
>
> http://stackoverflow.com/questions/7225070/php-array-delete-by-value-not-key
>
> Shouldn't we have something simple, like:
>
>     array_remove($array, $value) : array (returns a new array)
>
> and/or
>
>     array_delete(&$array, $value) : bool (modifies array directly)
>
> ?

It was amazing that this thread has close to 90 mails.

I've added some use cases of array_udelete() to wiki, since
some people fails to see how it could be useful. I also bring
back to `array_walk()` version of equivalent example. I just
don't see any reason why we should replace it with slower
foreach() version.

I think the RFC page is almost complete.

https://wiki.php.net/rfc/array_delete

Any more comments?

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #62383 — Levi Morrison — 2012-08-22T02:07:14+00:00

URL: https://externals.io/message/62201#62383 · In reply to: #62382

>
> Hi,
>
> 2012/8/16 Rasmus Schultz <rasmus@mindplay.dk>:
> > […]
>
> It was amazing that this thread has close to 90 mails.
>
> I've added some use cases of array_udelete() to wiki, since
> some people fails to see how it could be useful. I also bring
> back to `array_walk()` version of equivalent example. I just
> don't see any reason why we should replace it with slower
> foreach() version.
>
> I think the RFC page is almost complete.
>
> https://wiki.php.net/rfc/array_delete
>
> Any more comments?
>
> --
> Yasuo Ohgaki
> yohgaki@ohgaki.net

Take a look at:
http://php.net/manual/en/function.array-walk.php#refsect1-function.array-walk-parameters

Look at funcname parameter.  Notice:
> Only the values of the array may potentially be changed; its structure cannot be altered, i.e., the programmer cannot add, unset or reorder elements. If the callback does not respect this requirement, the behavior of this function is undefined, and unpredictable.

I'm just going to change the behavior back when you switch it to
array_walk. It's less clear and technically undefined.

---

## #62384 — Yasuo Ohgaki — 2012-08-22T02:13:47+00:00

URL: https://externals.io/message/62201#62384 · In reply to: #62383

Hi,

2012/8/22 Levi Morrison <morrison.levi@gmail.com>:
> 
> > […]
>
> Take a look at:
> http://php.net/manual/en/function.array-walk.php#refsect1-function.array-walk-parameters
>
> Look at funcname parameter.  Notice:
> > […]
>
> I'm just going to change the behavior back when you switch it to
> array_walk. It's less clear and technically undefined.

Ok, then my commit to the doc was outstanding still.
Old PHP was behaved badly with reference variables.
I'll remove obsolete statement.

I'll fix it later.
Thank you.

--
Yasuo Ohgaki
yohgaki@ohgaki.net
