[php] How do you reindex an array in PHP but with indexes starting from 1?

I have the following array, which I would like to reindex so the keys are reversed (ideally starting at 1):

Current array (edit: the array actually looks like this):

Array (

[2] => Object
    (
        [title] => Section
        [linked] => 1
    )

[1] => Object
    (
        [title] => Sub-Section
        [linked] => 1
    )

[0] => Object
    (
        [title] => Sub-Sub-Section
        [linked] => 
    )

)

How it should be:

Array (

[1] => Object
    (
        [title] => Section
        [linked] => 1
    )

[2] => Object
    (
        [title] => Sub-Section
        [linked] => 1
    )

[3] => Object
    (
        [title] => Sub-Sub-Section
        [linked] => 
    )

)

This question is related to php arrays indexing

The answer is


This will do what you want:

<?php

$array = array(2 => 'a', 1 => 'b', 0 => 'c');

array_unshift($array, false); // Add to the start of the array
$array = array_values($array); // Re-number

// Remove the first index so we start at 1
$array = array_slice($array, 1, count($array), true);

print_r($array); // Array ( [1] => a [2] => b [3] => c ) 

?>

Well, I would like to think that for whatever your end goal is, you wouldn't actually need to modify the array to be 1-based as opposed to 0-based, but could instead handle it at iteration time like Gumbo posted.

However, to answer your question, this function should convert any array into a 1-based version

function convertToOneBased( $arr )
{
    return array_combine( range( 1, count( $arr ) ), array_values( $arr ) );
}

EDIT

Here's a more reusable/flexible function, should you desire it

$arr = array( 'a', 'b', 'c' );

echo '<pre>';
print_r( reIndexArray( $arr ) );
print_r( reIndexArray( $arr, 1 ) );
print_r( reIndexArray( $arr, 2 ) );
print_r( reIndexArray( $arr, 10 ) );
print_r( reIndexArray( $arr, -10 ) );
echo '</pre>';

function reIndexArray( $arr, $startAt=0 )
{
    return ( 0 == $startAt )
        ? array_values( $arr )
        : array_combine( range( $startAt, count( $arr ) + ( $startAt - 1 ) ), array_values( $arr ) );
}

Why reindexing? Just add 1 to the index:

foreach ($array as $key => $val) {
    echo $key + 1, '<br>';
}

Edit   After the question has been clarified: You could use the array_values to reset the index starting at 0. Then you could use the algorithm above if you just want printed elements to start at 1.


Duplicate removal and reindex an array:

<?php  
   $oldArray = array('0'=>'php','1'=>'java','2'=>'','3'=>'asp','4'=>'','5'=>'mysql');
   //duplicate removal
   $fillteredArray = array_filter($oldArray);
   //reindexing actually happens  here
   $newArray = array_merge($filteredArray);
   print_r($newArray);
?>

$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;

Here is the best way:

# Array
$array = array('tomato', '', 'apple', 'melon', 'cherry', '', '', 'banana');

that returns

Array
(
    [0] => tomato
    [1] => 
    [2] => apple
    [3] => melon
    [4] => cherry
    [5] => 
    [6] => 
    [7] => banana
)

by doing this

$array = array_values(array_filter($array));

you get this

Array
(
    [0] => tomato
    [1] => apple
    [2] => melon
    [3] => cherry
    [4] => banana
)

Explanation

array_values() : Returns the values of the input array and indexes numerically.

array_filter() : Filters the elements of an array with a user-defined function (UDF If none is provided, all entries in the input table valued FALSE will be deleted.)


You can reindex an array so the new array starts with an index of 1 like this;

$arr = array(
  '2' => 'red',
  '1' => 'green',
  '0' => 'blue',
);

$arr1 = array_values($arr);   // Reindex the array starting from 0.
array_unshift($arr1, '');     // Prepend a dummy element to the start of the array.
unset($arr1[0]);              // Kill the dummy element.

print_r($arr);
print_r($arr1);

The output from the above is;

Array
(
    [2] => red
    [1] => green
    [0] => blue
)
Array
(
    [1] => red
    [2] => green
    [3] => blue
)

It feels like all of the array_combine() answers are all copying the same "mistake" (the unnecessary call of array_values()).

array_combine() ignores the keys of both parameters that it receives.

Code: (Demo)

$array = [
    2 => (object)['title' => 'Section', 'linked' => 1],
    1 => (object)['title' => 'Sub-Section', 'linked' => 1],
    0 => (object)['title' => 'Sub-Sub-Section', 'linked' => null]
];

var_export(array_combine(range(1, count($array)), $array));

Output:

array (
  1 => 
  (object) array(
     'title' => 'Section',
     'linked' => 1,
  ),
  2 => 
  (object) array(
     'title' => 'Sub-Section',
     'linked' => 1,
  ),
  3 => 
  (object) array(
     'title' => 'Sub-Sub-Section',
     'linked' => NULL,
  ),
)

Similar to Nick's contribution, I came to the same solution for reindexing an array, but enhanced the function a little since from PHP version 5.4, it doesn't work because of passing variables by reference. Example reindexing function is then like this using use keyword closure:

function indexArrayByElement($array, $element)
{
    $arrayReindexed = [];
    array_walk(
        $array,
        function ($item, $key) use (&$arrayReindexed, $element) {
            $arrayReindexed[$item[$element]] = $item;
        }
    );
    return $arrayReindexed;
}

Sorting is just a sort(), reindexing seems a bit silly but if it is needed this will do it. Though not in-place. Use array_walk() if you will do this in a bunch of places, just use a for-key-value loop if this is a one-time operation.

<?php

function reindex(&$item, $key, &$reindexedarr) {
    $reindexedarr[$key+1] = $item;
}

$arr = Array (2 => 'c', 1 => 'b', 0 => 'a');

sort($arr);
$newarr = Array();
array_walk($arr, reindex, &$newarr);
$arr = $newarr;
print_r($arr); // Array ( [1] => a [2] => b [3] => c )

?>

If it's OK to make a new array it's this:

$result = array();
foreach ( $array as $key => $val )
    $result[ $key+1 ] = $val;

If you need reversal in-place, you need to run backwards so you don't stomp on indexes that you need:

for ( $k = count($array) ; $k-- > 0 ; )
    $result[ $k+1 ] = $result[ $k ];
unset( $array[0] );   // remove the "zero" element

If you are not trying to reorder the array you can just do:

$array = array_reverse( $array );
$array = array_reverse( $array );

The array_reverse is very fast and it reorders as it reverses. Someone else showed me this a long time ago. So I can't take credit for coming up with it. But it is very simple and fast.


A more elegant solution:

$list = array_combine(range(1, count($list)), array_values($list));


Simply do this:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);

You can easily do it after use array_values() and array_filter() function together to remove empty array elements and reindex from an array in PHP.

array_filter() function The PHP array_filter() function remove empty array elements or values from an array in PHP. This will also remove blank, null, false, 0 (zero) values.

array_values() function The PHP array_values() function returns an array containing all the values of an array. The returned array will have numeric keys, starting at 0 and increase by 1.

Remove Empty Array Elements and Reindex

First let’s see the $stack array output :

<?php
  $stack = array("PHP", "HTML", "CSS", "", "JavaScript", null, 0);
  print_r($stack);
?>

Output:

Array
(
    [0] => PHP
    [1] => HTML
    [2] => CSS
    [3] => 
    [4] => JavaScript
    [5] => 
    [6] => 0
)

In above output we want to remove blank, null, 0 (zero) values and then reindex array elements. Now we will use array_values() and array_filter() function together like in below example:

<?php
  $stack = array("PHP", "HTML", "CSS", "", "JavaScript", null, 0);
  print_r(array_values(array_filter($stack)));
?>

Output:

Array
(
    [0] => PHP
    [1] => HTML
    [2] => CSS
    [3] => JavaScript
)

Here's my own implementation. Keys in the input array will be renumbered with incrementing keys starting from $start_index.

function array_reindex($array, $start_index)
{
    $array = array_values($array);
    $zeros_array = array_fill(0, $start_index, null);
    return array_slice(array_merge($zeros_array, $array), $start_index, null, true);
}

You may want to consider why you want to use a 1-based array at all. Zero-based arrays (when using non-associative arrays) are pretty standard, and if you're wanting to output to a UI, most would handle the solution by just increasing the integer upon output to the UI.

Think about consistency—both in your application and in the code you work with—when thinking about 1-based indexers for arrays.


I just found out you can also do a

array_splice($ar, 0, 0);

That does the re-indexing inplace, so you don't end up with a copy of the original array.


Similar to @monowerker, I needed to reindex an array using an object's key...

$new = array();
$old = array(
  (object)array('id' => 123),
  (object)array('id' => 456),
  (object)array('id' => 789),
);
print_r($old);

array_walk($old, function($item, $key, &$reindexed_array) {
  $reindexed_array[$item->id] = $item;
}, &$new);

print_r($new);

This resulted in:

Array
(
    [0] => stdClass Object
        (
            [id] => 123
        )
    [1] => stdClass Object
        (
            [id] => 456
        )
    [2] => stdClass Object
        (
            [id] => 789
        )
)
Array
(
    [123] => stdClass Object
        (
            [id] => 123
        )
    [456] => stdClass Object
        (
            [id] => 456
        )
    [789] => stdClass Object
        (
            [id] => 789
        )
)

The fastest way I can think of

array_unshift($arr, null);
unset($arr[0]);
print_r($arr);

And if you just want to reindex the array(start at zero) and you have PHP +7.3 you can do it this way

array_unshift($arr);

I believe array_unshift is better than array_values as the former does not create a copy of the array.


Examples related to php

I am receiving warning in Facebook Application using PHP SDK Pass PDO prepared statement to variables Parse error: syntax error, unexpected [ Preg_match backtrack error Removing "http://" from a string How do I hide the PHP explode delimiter from submitted form results? Problems with installation of Google App Engine SDK for php in OS X Laravel 4 with Sentry 2 add user to a group on Registration php & mysql query not echoing in html with tags? How do I show a message in the foreach loop?

Examples related to arrays

PHP array value passes to next row Use NSInteger as array index How do I show a message in the foreach loop? Objects are not valid as a React child. If you meant to render a collection of children, use an array instead Iterating over arrays in Python 3 Best way to "push" into C# array Sort Array of object by object field in Angular 6 Checking for duplicate strings in JavaScript array what does numpy ndarray shape do? How to round a numpy array?

Examples related to indexing

numpy array TypeError: only integer scalar arrays can be converted to a scalar index How to print a specific row of a pandas DataFrame? What does 'index 0 is out of bounds for axis 0 with size 0' mean? How does String.Index work in Swift Pandas KeyError: value not in index Update row values where certain condition is met in pandas Pandas split DataFrame by column value Rebuild all indexes in a Database How are iloc and loc different? pandas loc vs. iloc vs. at vs. iat?