PHPで配列のインデックスを再作成するにはどうすればよいですか?


157

次の配列があります。キーを逆にするために、インデックスを再作成したいと思います(理想的には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
どこが逆転していますか?
ガンボ

最初の例への私の編集を参照してください
meleyal

そして、なぜ最初の要素のインデックスが1である必要があるのですか?単なるフォーマットの問題ですか、それとも内部処理ですか?
ガンボ

これは、URLセグメントを取得する関数のパラメーターとして使用されます。たとえば、get_url_segment(1)のように、このページで「questions」を返します
meleyal

回答:


445

ゼロからインデックスを再作成する場合は、次の手順を実行します。

$iZero = array_values($arr);

1つから開始する必要がある場合は、以下を使用します。

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

使用されている関数のマニュアルページは次のとおりです。


1
範囲が0のcount($ arr)-1)を使用して、インデックスが0の配列を取得する必要があります。
Max Hartshorn、2015

これはすばらしい方法です。代わりに、array_unshift($ arr、 '')を使用してインデックスがゼロの要素を追加し、次にunset($ arr [0])を使用して削除して、すべてのインデックスを1つ上に移動することもできます。array_combine()よりも高速かもしれません。か
どう

array_values配列のコピーを返すことに注意してください。したがって、配列への参照がある場合は、そのarray_splice方が良いでしょう。@imagiroソリューションを参照してください。
Nux

array_values()常にインデックス0で開始する場合にのみ機能させます。
kishor10d

55

これが最良の方法です:

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

それが戻る

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

これを行うことによって

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

あなたはこれを手に入れます

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

説明

array_values() :入力配列とインデックスの値を数値で返します。

array_filter():ユーザ定義関数で配列の要素をフィルタリング(UDF 何も提供されない場合入力テーブルのすべてのエントリは、値のFALSEは削除されます。)


3
順序を気にしない場合は、単にsort($ array);することもできます。
Peter M. Elias

array_filter()サンプルデータとはまったく無関係のようです。
mickmackusa

13

私はあなたがまたできることを見つけました

array_splice($ar, 0, 0);

これでインデックスの再作成が行われるため、元の配列のコピーが作成されることはありません。


9

なぜインデックスを再作成するのですか?インデックスに1を追加するだけです。

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

編集    質問が明確になった後:を使用しarray_valuesて、インデックスを0からリセットできます。次に、印刷された要素を1から開始する場合は、上記のアルゴリズムを使用できます。


この質問に対する過小評価された回答:)
jminkler

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

5

これはあなたが望むことをします:

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

?>

5

1ベースの配列を使用する理由を検討することをお勧めします。ゼロベースの配列(非連想配列を使用する場合)はかなり標準的であり、UIに出力したい場合、ほとんどの場合、UIへの出力時に整数を増やすだけでソリューションを処理します。

配列の1ベースのインデクサーについて考えるときは、アプリケーションと使用するコードの両方で一貫性を考慮してください。


2
これは、ビジネスレイヤーとプレゼンテーションレイヤーの分離に直接相関します。プレゼンテーションに対応するためにロジックのコードを変更している場合、悪いことをしています。たとえば、これをコントローラーに対して実行した場合、コントローラーは突然、使用するビューレンダラー(php、json、xml、rssなど)のデータを準備するのではなく、特定のビューレンダラーに関連付けられます
Tres

5

よりエレガントなソリューション:

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


6
あなたはこれをエレガントと呼びますか?
ジュリアン

5

配列のインデックスを再作成して、新しい配列が次のように1のインデックスで始まるようにすることができます。

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

上記の出力は次のとおりです。

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

array_valuesここで使用する必要はありません。私の答えを見てください。
雨の

4

@monowerkerと同様に、オブジェクトのキーを使用して配列のインデックスを再作成する必要がありました...

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

これは次の結果をもたらしました:

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

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は非常に高速で、逆順になると並べ替えられます。他の誰かがずっと前にこれを見せてくれました。だから私はそれを思いついたとは言えません。しかし、それは非常にシンプルで高速です。


2

Nickの貢献と同じように、配列のインデックスを再作成するための同じソリューションにたどり着きましたが、PHPバージョン5.4以降、変数を参照で渡すため機能しないため、関数を少し拡張しました。次に、useキーワードクロージャを使用した再インデックス関数の例は次のようになります。

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

1

ここに私自身の実装があります。入力配列のキーは、$ 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);
}


1

array_values()とarray_filter()関数を一緒に使用して、空の配列要素を削除し、PHPの配列からインデックスを再作成した後、これを簡単に行うことができます。

array_filter()関数 PHPのarray_filter()関数は、PHPの配列から空の配列要素または値を削除します。これにより、空白、null、false、0(ゼロ)の値も削除されます。

array_values()関数 PHPのarray_values()関数は、配列のすべての値を含む配列を返します。返される配列には、0から始まり1ずつ増える数値キーがあります。

空の配列要素を削除してインデックスを再作成する

まず$ stack配列の出力を見てみましょう:

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

出力:

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

上記の出力では、空白、null、0(ゼロ)の値を削除してから、配列要素のインデックスを再作成しています。次の例のように、array_values()関数とarray_filter()関数を一緒に使用します。

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

出力:

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

array_filter()OPのサンプルデータとはまったく無関係のようです。
mickmackusa

1

重複した削除と配列のインデックスの再作成:

<?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);
?>

array_filter()OPのサンプルデータとはまったく無関係のようです。
mickmackusa

1

私が考えることができる最も速い方法

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

配列のインデックスを再作成したい場合(ゼロから開始)、PHP +7.3を使用している場合は、次のようにすることができます

array_unshift($arr);

前者は配列のコピーを作成しないので、私array_unshiftはより良いと信じarray_valuesています。


0

すべてのarray_combine()答えがすべて同じ「間違い」をコピーしているように感じます(の不要な呼び出しarray_values())。

array_combine() 受け取った両方のパラメーターのキーを無視します。

コード:(デモ

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

出力:

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

0

並べ替えは単にsort()であり、インデックスの再作成は少しばかげているように見えますが、必要な場合はこれを実行します。インプレースではありませんが。多数の場所でこれを行う場合はarray_walk()を使用します。これが1回限りの操作である場合は、for-key-valueループを使用します。

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

?>

-10

新しい配列を作成してもよい場合は、次のようになります。

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

インプレースで逆転が必要な場合は、逆方向に実行して、必要なインデックスを踏まないようにする必要があります。

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

20
この問題に対する答えはループを必要としません。答えの重要な部分は、array_values()0ベースの配列を取得するために使用し、1ベースの配列が本当に必要な場合は、その結果を調整することです。
grantwparks 2009
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.