如何在PHP中重新索引数组,但索引从1开始?

178

我有一个数组,我想重新索引它,使得键值反转(最好从1开始):

当前的数组(编辑: 实际上数组长这样):

Array (

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

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

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

)

应该如何实现:

Array (

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

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

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

)

1
哪里有反转的东西? - Gumbo
请看我对第一个示例的编辑。 - meleyal
你为什么需要第一个元素的索引为1?只是格式问题还是用于内部处理? - Gumbo
它将被用作函数的参数,以获取URL段,例如get_url_segment(1)将在此页面上返回“questions”。 - meleyal
12个回答

504
如果你想重新从零开始索引,只需按照以下步骤操作:
$iZero = array_values($arr);

如果你需要从一开始,那么请使用以下内容:
$iOne = array_combine(range(1, count($arr)), array_values($arr));

以下是所使用函数的手册页面:

1
你应该使用 range(0, count($arr) - 1) 来获取从零开始的索引数组。 - Max Hartshorn
很好,或者你可以尝试使用array_unshift($arr,'')来添加一个零索引元素,然后使用unset($arr[0])将其删除,从而将所有索引上移一位。这可能比array_combine()更快。或者也可能不是 :) - Steve Horvath
请注意array_values返回的是一个数组的副本。所以如果你有对该数组的引用,那么使用array_splice会更好。请参考@imagiro的解决方案。 - Nux
2
@MaxHartshorn,这不是这个问题所要求的! - mickmackusa

11

为什么要重新索引?只需将索引加1即可:

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

编辑:问题已经澄清:您可以使用array_values重置索引,从0开始。如果您只想使打印的元素从1开始,请使用上面的算法。


9

您可以通过以下方式重新索引一个数组,使新的数组从1开始索引:

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

$arr1 = array_values($arr);   // Reindex the array starting from zero*.
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);

以上的输出是;
Array
(
    [2] => red
    [1] => green
    [0] => blue
)
Array
(
    [1] => red
    [2] => green
    [3] => blue
)

*注意:如果所有输入键都是数字,则不需要使用array_values()命令。自PHP 4.3以来,array_unshift()会重新索引传入数组的数字键。


调用 array_values() 是不必要的,对吗?或者有我没有考虑到的边缘情况吗? - mickmackusa
@mickmackusa array_values() 调用是必要的。它会重新索引数组,从零开始。 - Nigel Alderton
@mickmackusa array_unshift() 只会重新索引数字键。但是如果所有的键都是数字,那么确实不需要使用 array_values()。 (问题有点含糊,因为问题标题与问题内容不同。) - Nigel Alderton

7
这将实现您想要的功能:
<?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 ) 

?>

7

你可能需要考虑为什么要使用基于1的数组。在非关联数组中,基于0的数组是相当标准的,如果你想要输出到UI界面,大多数情况下只需要在输出到UI时增加整数即可。

在考虑数组的基于1的索引器时,请考虑应用程序和代码的一致性。


3
这与业务层和表示层之间的分离直接相关。如果你要修改逻辑代码以适应表示层,那么你正在做一些不好的事情。例如,如果你在控制器中这样做,那么你的控制器将会与特定的视图渲染器绑定,而不是为任何可能使用的视图渲染器(如php、json、xml、rss等)准备数据。 - Tres

6

我认为,无论您的最终目标是什么,您实际上不需要修改数组从而将其从0基转换为1基,而可以像Gumbo发布的那样在迭代时处理它。

然而,回答您的问题,此函数应将任何数组转换为1基版本。

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

编辑

如果您需要更具可重用性和灵活性的函数,可以使用以下函数:

$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 ) );
}

6
更加优雅的解决方案:
$list = array_combine(range(1, count($list)), array_values($list));

6
我能想到最快的方法。
array_unshift($arr, null);
unset($arr[0]);
print_r($arr);

如果你只想重新索引数组(从零开始),并且你使用的是 PHP +7.3,你可以通过以下方式实现。

array_unshift($arr);

我认为array_unshiftarray_values更好,因为前者不会创建数组的副本。

变更日志

版本 描述
7.3.0 现在可以只用一个参数调用此函数。以前需要至少两个参数。

-- https://www.php.net/manual/zh/function.array-unshift.php#refsect1-function.array-unshift-changelog


我的错误。 这是一个有缺陷的测试。https://3v4l.org/cetL8 array_unshift() 只有一个参数,什么也不添加。 - mickmackusa

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

3

如果您不想重新排序数组,只需执行以下操作:

$array = array_reverse( $array );

然后再调用一次,将它恢复为原来的顺序:

$array = array_reverse( $array );

array_reverse()函数在翻转数组时重新索引。很久以前有人向我展示了这个函数,所以我不能为它的发明者而自豪。但是这个函数非常简单快速。

结果是一个从0开始索引的数组。https://3v4l.org/iQgVh

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

1
这个问题不是要求从0开始的索引数组;这个问题要求从1开始的连续键。这个答案没有提供所需的输出。https://3v4l.org/f6Pa4 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接