179

I need to remove array item with given value:

if (in_array($id, $items)) {
    $items = array_flip($items);
    unset($items[ $id ]);
    $items = array_flip($items);
}

Could it be done in shorter (more efficient) way?

0

10 Answers 10

442

It can be accomplished with a simple one-liner.

Having this array:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');

You can do:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));

And the value of $arr will be:

array('nice_item', 'another_liked_item')
Sign up to request clarification or add additional context in comments.

8 Comments

No, it does works with referenced arrays, the array_diff function is non-destructive, it returns a new array.
@srcspider why not? $referenced = array_diff($referenced, $items_to_remove);
$referenced is now pointing to a new array, the array you wanted to change still has the old values.
@srcspider well, you tell me what's going on here then... codepad.org/11ZhiFP0
my bad; php's variable aliasing gimmick always trips me over >.>
|
37

I am adding a second answer. I wrote a quick benchmarking script to try various methods here.

$arr = array(0 => 123456);
for($i = 1; $i < 500000; $i++) {
    $arr[$i] = rand(0,PHP_INT_MAX);
}

shuffle($arr);
$arr2 = $arr;
$arr3 = $arr;

/** 
 * Method 1 - array_search()
 */
$start = microtime(true);
while(($key = array_search(123456,$arr)) !== false) {
    unset($arr[$key]);
}
echo count($arr). ' left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 2 - basic loop
 */
$start = microtime(true);
foreach($arr2 as $k => $v) {
    if ($v == 123456) {
        unset($arr2[$k]);
    }
}
echo count($arr2). 'left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 3 - array_keys() with search parameter
 */
$start = microtime(true);
$keys = array_keys($arr3,123456);
foreach($keys as $k) {
    unset($arr3[$k]);
}
echo count($arr3). 'left, in '.(microtime(true) - $start).' seconds<BR>';

The third method, array_keys() with the optional search parameter specified, seems to be by far the best method. Output example:

499999 left, in 0.090957164764404 seconds
499999left, in 0.43156313896179 seconds
499999left, in 0.028877019882202 seconds

Judging by this, the solution I would use then would be:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}

2 Comments

I think array_search is much more readable code than using the array_diff method. Upvote
@zombat I wonder if order has anything to do with the results. It is possible that shuffle put the value we are searching for either closer to the front or end. Other than that... +1
34

How about:

if (($key = array_search($id, $items)) !== false) unset($items[$key]);

or for multiple values:

while(($key = array_search($id, $items)) !== false) {
    unset($items[$key]);
}

This would prevent key loss as well, which is a side effect of array_flip().

1 Comment

won't work if $id is first array element, better this way: if ( ($key = array_search($id, $items)) !== false) unset($items[$key]);
17

to remove $rm_val from $arr

unset($arr[array_search($rm_val, $arr)]);

Comments

9

The most powerful solution would be using array_filter, which allows you to define your own filtering function.

But some might say it's a bit overkill, in your situation...
A simple foreach loop to go trough the array and remove the item you don't want should be enough.

Something like this, in your case, should probably do the trick :

foreach ($items as $key => $value) {
    if ($value == $id) {
        unset($items[$key]);
        // If you know you only have one line to remove, you can decomment the next line, to stop looping
        //break;
    }
}

Comments

6

Try array_search()

2 Comments

I just read the documentation, and it recommend to use array_keys() to find all the keys associated to a value.
@Savageman - Agreed. I ran a quick benchmark and array_keys() seems to perform better than array_search() for this task.
6

Your solutions only work if you have unique values in your array

See:

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

A better way would be unset with array_search, in a loop if neccessary.

1 Comment

you are right, but in this particular case I'm pretty sure that values are unique :)
5

w/o flip:

<?php
foreach ($items as $key => $value) {
    if ($id === $value) {
        unset($items[$key]);
    }
}

Comments

5
function deleteValyeFromArray($array,$value)
{
   foreach($array as $key=>$val)
   {
      if($val == $value)
      {
         unset($array[$key]);
      }
   }
   return $array;
}

Comments

4

You can use array_splice function for this operation Ref : array_splice

array_splice($array, array_search(58, $array ), 1);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.