173

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] => 
    )

)
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
meleyal
  • 30,494
  • 24
  • 69
  • 77

21 Answers21

484

If you want to re-index starting to zero, simply do the following:

$iZero = array_values($arr);

If you need it to start at one, then use the following:

$iOne = array_combine(range(1, count($arr)), array_values($arr));

Here are the manual pages for the functions used:

Andrew Moore
  • 90,677
  • 30
  • 161
  • 174
59

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.)

Bram Vanroy
  • 24,991
  • 21
  • 120
  • 214
Sandra
  • 1,518
  • 13
  • 21
16

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.

imagiro
  • 442
  • 5
  • 6
11

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.

Gumbo
  • 620,600
  • 104
  • 758
  • 828
6

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 ) );
}
Peter Bailey
  • 103,526
  • 30
  • 178
  • 200
5

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
)
Nigel Alderton
  • 2,145
  • 2
  • 23
  • 53
5

A more elegant solution:

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

5

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 ) 

?>
Greg
  • 307,243
  • 53
  • 363
  • 328
5

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.

Michael Trausch
  • 3,157
  • 1
  • 20
  • 29
  • 3
    This directly correlates to the separation between the business layer and presentation layer. If you are modifying code in your logic to accommodate presentation, you are doing bad things. For example, if you did this for a controller, suddenly your controller is tied to a specific view renderer rather preparing data for whatever view renderer it may utilize (php, json, xml, rss, etc.) – Tres Apr 13 '11 at 23:46
4

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
        )
)
Nick
  • 2,597
  • 1
  • 35
  • 56
3

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.

Mark
  • 39
  • 2
3
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;
Tom Haigh
  • 56,170
  • 20
  • 110
  • 140
2

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;
}
VLS
  • 2,270
  • 4
  • 21
  • 17
FantomX1
  • 1,317
  • 2
  • 11
  • 20
2

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.

Rain
  • 2,696
  • 1
  • 17
  • 35
1

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);
}
Mustapha Hadid
  • 1,154
  • 14
  • 26
1

Simply do this:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);
Roham Rafii
  • 2,793
  • 7
  • 34
  • 44
1

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
)
Abdur Rehman
  • 3,112
  • 5
  • 32
  • 47
1

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,
  ),
)
mickmackusa
  • 37,596
  • 11
  • 75
  • 105
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);
?>
Abdur Rehman
  • 3,112
  • 5
  • 32
  • 47
Sam Arul Raj T
  • 1,712
  • 16
  • 21
0

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 )

?>
Abdur Rehman
  • 3,112
  • 5
  • 32
  • 47
monowerker
  • 2,879
  • 1
  • 23
  • 23
-9

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
Jason Cohen
  • 78,683
  • 26
  • 106
  • 112
  • 20
    Any answer to this problem should not need a loop. The key part of the answer is using `array_values()` to get a 0-based array and then making some adjustment to that result if a 1-based array is *really* required. – grantwparks Sep 25 '09 at 19:26