154

I just used array_filter to remove entries that had only the value '' from an array, and now I want to apply certain transformations on it depending on the placeholder starting from 0, but unfortunately it still retains the original index. I looked for a while and couldn't see anything, perhaps I just missed the obvious, but my question is...

How can I easily reset the indexes of the array to begin at 0 and go in order in the NEW array, rather than have it retain old indexes?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
jel402
  • 1,543
  • 2
  • 9
  • 4
  • Possible duplicate of [php array\_filter without key preservation](http://stackoverflow.com/questions/2653017/php-array-filter-without-key-preservation) – Yep_It's_Me Mar 22 '16 at 03:42
  • Unless you are absolutely certain you don't have any empty/zero-ish/falsey values in your array, I must urge you not to use `array_filter()` -- you may purge more than you intend to. Here is some explanation with a demo: http://stackoverflow.com/a/43657056/2943403 – mickmackusa Apr 29 '17 at 09:36

4 Answers4

314

If you call array_values on your array, it will be reindexed from zero.

Salman A
  • 262,204
  • 82
  • 430
  • 521
Daniel Vandersluis
  • 91,582
  • 23
  • 169
  • 153
  • 3
    The link no longer work, use http://php.net/manual/en/function.array-values.php instead. I can't update it, as i need to change at least 6 characters. – Rasmus Hansen Feb 16 '19 at 15:15
64

If you are using Array filter do it as follows

$NewArray = array_values(array_filter($OldArray));
user2182143
  • 992
  • 9
  • 10
17

Use array_values():

<?php

$array = array('foo', 'bar', 'baz');
$array = array_filter($array, function ($var) {
    return $var !== 'bar';
});

print_r($array); // indexes 0 and 2
print_r(array_values($array)); // indexes 0 and 1
Ed Mazur
  • 3,042
  • 3
  • 21
  • 21
17

I worry about how many programmers have innocently copy/pasted the array_values(array_filter()) method into their codes -- I wonder how many programmers unwittingly ran into problems because of array_filter's greed. Or worse, how many people never discovered that the function purges too many values from the array...

I will present a better alternative for the two-part process of stripping NULL elements from an array and re-indexing the keys.

However, first, it is extremely important that I stress the greedy nature of array_filter() and how this can silently monkeywrench your project. Here is an array with mixed values in it that will expose the trouble:

$array=['foo',NULL,'bar',0,false,null,'0',''];

Null values will be removed regardless of uppercase/lowercase.

But look at what remains in the array when we use array_values() & array_filter():

array_values(array_filter($array));

Output array ($array):

array (
  0 => 'foo',
  1 => 'bar'
)
// All empty, zero-ish, falsey values were removed too!!!

Now look at what you get with my method that uses array_walk() & is_null() to generate a new filtered array:

array_walk($array,function($v)use(&$filtered){if(!is_null($v)){$filtered[]=$v;}});

This can be written over multiple lines for easier reading/explaining:

array_walk(                      // iterate each element of an input array
    $array,                      // this is the input array
    function($v)use(&$filtered){ // $v is each value, $filter (output) is declared/modifiable
        if(!is_null($v)){        // this literally checks for null values
            $filtered[]=$v;      // value is pushed into output with new indexes
        }
    }
);

Output array ($filter):

array (
  0 => 'foo',
  1 => 'bar',
  2 => 0,
  3 => false,
  4 => '0',
  5 => '',
)

With my method you get your re-indexed keys, all of the non-null values, and none of the null values. A clean, portable, reliable one-liner for all of your array null-filtering needs. Here is a demonstration.



Similarly, if you want to remove empty, false, and null elements (retaining zeros), these four methods will work:

var_export(array_values(array_diff($array,[''])));

or

var_export(array_values(array_diff($array,[null])));

or

var_export(array_values(array_diff($array,[false])));

or

var_export(array_values(array_filter($array,'strlen')));

Output:

array (
  0 => 'foo',
  1 => 'bar',
  2 => 0,
  3 => '0',
)

Finally, for anyone who prefers the syntax of language constructs, you can also just push qualifying values into a new array to issue new indexes.

$array=['foo', NULL, 'bar', 0, false, null, '0', ''];

$result = [];
foreach ($array as $value) {
    if (strlen($value)) {
        $result[] = $value;
    }
}

var_export($result);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • 3
    Won't things behave in exactly the expected way if you write `array_values(array_filter($arr, function($el) {return $el !== '';}))`? That seems like the natural way to do what the OP is asking about. – Casey Mar 21 '18 at 15:04
  • 1
    Yes. My point is that developers should avoid the urge to use the default behavior of `array_filter()` unless their intimate knowledge of the data permits greedy filtering without side effects. (A further caution: `empty()` behaves in this same fashion and also includes an empty array in its greediness. ) – mickmackusa Mar 21 '18 at 21:22
  • 5
    This reply answers completely different question, not related to the original one in any way, shape or form. – AnrDaemon Nov 12 '18 at 20:11
  • This answer does exactly the task asked "reindex an array after filtering an array". I also happen to be giving warning about `array_filter()` which is relevant because Google results will probably direct researchers here who have searched for "reindex after array_filter". The fact that my answer DOES provide several ways to achieve the desired result is proof that this answer is appropriate/relevant. If you are still not satisfied, I'll add a language construct alternative now. – mickmackusa Nov 12 '18 at 20:54
  • 5
    `array_filter()` behaves exactly like you'd expect based on what it says in the manual: http://php.net/manual/en/function.array-filter.php "If no callback is supplied, all entries of array equal to FALSE (see converting to boolean) will be removed." And it should be common knowledge among PHP programmers that 0, null, false, '' and '0' all evaluate to false when coerced to boolean. – madsen Mar 05 '19 at 11:16
  • 1
    Thing is, most people don't know what to expect. You do, I do, but many don't. I posted this answer to help people who don't know. – mickmackusa Mar 05 '19 at 11:18