211

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)
}
Naftali
  • 144,921
  • 39
  • 244
  • 303
TuK
  • 3,556
  • 4
  • 24
  • 24

9 Answers9

480

Try this:

$array = array_values($array);

Using array_values()

Naftali
  • 144,921
  • 39
  • 244
  • 303
  • 7
    +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. – Lightness Races in Orbit May 09 '11 at 22:20
  • 18
    Yes, ordering is definitely maintained. Would be a hideous function if it reordered it! :) – webbiedave May 09 '11 at 22:26
  • 1
    @webbiedave sorry, but that is not true. It does actually reorder my array. Very very strange. – FooBar Jun 23 '14 at 16:28
  • My solution was to use `ksort`. I simply needed the values, in the order the keys was set, but array_values would reorder them. `ksort` solved my issue! – FooBar Jun 24 '14 at 09:24
  • 4
    always go for the easy concise solutions :) – Bruce Lim Oct 16 '14 at 01:23
  • 1
    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. –  Feb 20 '17 at 00:09
  • 1
    That is what the question asked @OverlordvI it asked for zero based keys and not string based keys. You won't have an issue of rebasing with string based keys – Naftali Feb 20 '17 at 00:12
21

Got another interesting method:

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

$array = array_merge($array); 

Now the $array keys are reset.

Web_Developer
  • 1,251
  • 2
  • 18
  • 34
14

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.

Demian Brecht
  • 21,135
  • 5
  • 42
  • 46
  • 9
    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' – NotGaeL Aug 23 '13 at 18:14
  • 1
    @elcodedocle Then don't use a `foreach` loop. Use the standard `i Loop` and simply reset i after a splice. Also, [**`Working sample here.`**](http://ideone.com/liyoh) is not working. – SpYk3HH Jan 23 '14 at 14:06
  • Broken link, could you fix it? – Michel Ayres Oct 21 '14 at 16:45
  • should work if you loop reverse from higher to lower index – Simone Bonelli Sep 12 '22 at 16:20
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.

Community
  • 1
  • 1
SpYk3HH
  • 22,272
  • 11
  • 70
  • 81
  • Perfect solution with `splice` for really big arrays, because there is no copy needed. So I get not in memory-problems. – Sascha Sep 06 '20 at 01:00
3

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

Rockin4Life33
  • 2,240
  • 1
  • 31
  • 29
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));
slfan
  • 8,950
  • 115
  • 65
  • 78
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

user229044
  • 232,980
  • 40
  • 330
  • 338
upful
  • 850
  • 10
  • 26
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);
Kerem
  • 11,377
  • 5
  • 59
  • 58
-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);
John K
  • 55
  • 1
  • 3
  • 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. – Rockin4Life33 Mar 20 '19 at 17:45