212

I have an array:

$array = array(1,2,3,4,5);

If I were to dump the contents of the array they would look like this:

array(5) {
  [0] => int(1)
  [1] => int(2)
  [2] => int(3)
  [3] => int(4)
  [4] => int(5)
}

When I loop through and unset certain keys, the index gets all jacked up.

foreach($array as $i => $info)
{
  if($info == 1 || $info == 2)
  {
    unset($array[$i]);
  }
}

Subsequently, if I did another dump now it would look like:

array(3) {
  [2] => int(3)
  [3] => int(4)
  [4] => int(5)
}

Is there a proper way to reset the array so it's elements are Zero based again ??

array(3) {
  [0] => int(3)
  [1] => int(4)
  [2] => int(5)
}
0

9 Answers 9

481

Try this:

$array = array_values($array);

Using array_values()

Sign up to request clarification or add additional context in comments.

7 Comments

+1. I note that the manual does not explicitly state that ordering will be maintained, but I can't see why it wouldn't be.
Yes, ordering is definitely maintained. Would be a hideous function if it reordered it! :)
@webbiedave sorry, but that is not true. It does actually reorder my array. Very very strange.
always go for the easy concise solutions :)
While this is an easy solution when the array is already numbered, it doesn't work when the key is set as text, like it would be as part of an HTML form. If you are relying on unique key values to identify the output from a form, one of the methods below works better.
|
21

Got another interesting method:

$array = array('a', 'b', 'c', 'd'); 
unset($array[2]); 

$array = array_merge($array); 

Now the $array keys are reset.

Comments

15

Use array_splice rather than unset:

$array = array(1,2,3,4,5);
foreach($array as $i => $info)
{
  if($info == 1 || $info == 2)
  {
    array_splice($array, $i, 1);
  }
}

print_r($array);

Working sample here.

4 Comments

This is not working. splice would be awesome but you can't use it inside a for/foreach loop because it rearranges the index every time you call it, so the index of the foreach loop doesn't point to the next element but to the element with that position on the rearranged array. You can see in you example you are deleting the value '3' and leaving the value '2' when you should be deleting only values '1' and '2'
@elcodedocle Then don't use a foreach loop. Use the standard i Loop and simply reset i after a splice. Also, Working sample here. is not working.
Broken link, could you fix it?
should work if you loop reverse from higher to lower index
6

Just an additive.

I know this is old, but I wanted to add a solution I don't see that I came up with myself. Found this question while on hunt of a different solution and just figured, "Well, while I'm here."

First of all, Neal's answer is good and great to use after you run your loop, however, I'd prefer do all work at once. Of course, in my specific case I had to do more work than this simple example here, but the method still applies. I saw where a couple others suggested foreach loops, however, this still leaves you with after work due to the nature of the beast. Normally I suggest simpler things like foreach, however, in this case, it's best to remember good old fashioned for loop logic. Simply use i! To maintain appropriate index, just subtract from i after each removal of an Array item.

Here's my simple, working example:

$array = array(1,2,3,4,5);

for ($i = 0; $i < count($array); $i++) {
    if($array[$i] == 1 || $array[$i] == 2) {
        array_splice($array, $i, 1);
        $i--;
    }
}

Will output:

array(3) {
    [0]=> int(3)
    [1]=> int(4)
    [2]=> int(5)
}

This can have many simple implementations. For example, my exact case required holding of latest item in array based on multidimensional values. I'll show you what I mean:

$files = array(
    array(
        'name' => 'example.zip',
        'size' => '100000000',
        'type' => 'application/x-zip-compressed',
        'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
        'deleteUrl' => 'server/php/?file=example.zip',
        'deleteType' => 'DELETE'
    ),
    array(
        'name' => 'example.zip',
        'size' => '10726556',
        'type' => 'application/x-zip-compressed',
        'url' => '28188b90db990f5c5f75eb960a643b96/example.zip',
        'deleteUrl' => 'server/php/?file=example.zip',
        'deleteType' => 'DELETE'
    ),
    array(
        'name' => 'example.zip',
        'size' => '110726556',
        'type' => 'application/x-zip-compressed',
        'deleteUrl' => 'server/php/?file=example.zip',
        'deleteType' => 'DELETE'
    ),
    array(
        'name' => 'example2.zip',
        'size' => '12356556',
        'type' => 'application/x-zip-compressed',
        'url' => '28188b90db990f5c5f75eb960a643b96/example2.zip',
        'deleteUrl' => 'server/php/?file=example2.zip',
        'deleteType' => 'DELETE'
    )
);

for ($i = 0; $i < count($files); $i++) {
    if ($i > 0) {
        if (is_array($files[$i-1])) {
            if (!key_exists('name', array_diff($files[$i], $files[$i-1]))) {
                if (!key_exists('url', $files[$i]) && key_exists('url', $files[$i-1])) $files[$i]['url'] = $files[$i-1]['url'];
                $i--;
                array_splice($files, $i, 1);
            }
        }
    }
}

Will output:

array(1) {
    [0]=> array(6) {
            ["name"]=> string(11) "example.zip"
            ["size"]=> string(9) "110726556"
            ["type"]=> string(28) "application/x-zip-compressed"
            ["deleteUrl"]=> string(28) "server/php/?file=example.zip"
            ["deleteType"]=> string(6) "DELETE"
            ["url"]=> string(44) "28188b90db990f5c5f75eb960a643b96/example.zip"
        }
    [1]=> array(6) {
            ["name"]=> string(11) "example2.zip"
            ["size"]=> string(9) "12356556"
            ["type"]=> string(28) "application/x-zip-compressed"
            ["deleteUrl"]=> string(28) "server/php/?file=example2.zip"
            ["deleteType"]=> string(6) "DELETE"
            ["url"]=> string(45) "28188b90db990f5c5f75eb960a643b96/example2.zip"
        }
}

As you see, I manipulate $i before the splice as I'm seeking to remove the previous, rather than the present item.

1 Comment

Perfect solution with splice for really big arrays, because there is no copy needed. So I get not in memory-problems.
4

I use $arr = array_merge($arr); to rebase an array. Simple and straightforward.

Comments

2

100% working for me ! After unset elements in array you can use this for re-indexing the array

$result=array_combine(range(1, count($your_array)), array_values($your_array));

Comments

1

Late answer but, after PHP 5.3 could be so;

$array = array(1, 2, 3, 4, 5);
$array = array_values(array_filter($array, function($v) {
    return !($v == 1 || $v == 2);
}));
print_r($array);

Comments

1

Or you can make your own function that passes the array by reference.

function array_unset($unsets, &$array) {
  foreach ($array as $key => $value) {
    foreach ($unsets as $unset) {
      if ($value == $unset) {
        unset($array[$key]);
        break;
      }
    }
  }
  $array = array_values($array);
}

So then all you have to do is...

$unsets = array(1,2);
array_unset($unsets, $array);

... and now your $array is without the values you placed in $unsets and the keys are reset

Comments

-2

In my situation, I needed to retain unique keys with the array values, so I just used a second array:

$arr1 = array("alpha"=>"bravo","charlie"=>"delta","echo"=>"foxtrot");
unset($arr1);

$arr2 = array();
foreach($arr1 as $key=>$value) $arr2[$key] = $value;
$arr1 = $arr2
unset($arr2);

1 Comment

1) You unset($arr1) which will make it NOT available to iterate over in your loop. 2) You're missing the semicolon on the second to last line. This code snippet will not run.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.