Comment réindexer un tableau en PHP?


157

J'ai le tableau suivant, que je voudrais réindexer pour que les clés soient inversées (idéalement à partir de 1):

Tableau actuel ( modifier: le tableau ressemble en fait à ceci):

Array (

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

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

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

)

Comment ça devrait être:

Array (

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

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

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

)

1
Où y a-t-il quelque chose d'inversé?
Gumbo le

Voir ma modification du premier exemple
meleyal

Et pourquoi avez-vous besoin que l'index du premier élément soit 1? Juste une question de format ou pour un traitement interne?
Gumbo

Il sera utilisé comme paramètre pour une fonction pour obtenir le segment a url, quelque chose comme get_url_segment (1) retournerait par exemple sur cette page "questions"
meleyal

Réponses:


445

Si vous souhaitez réindexer à partir de zéro, procédez comme suit:

$iZero = array_values($arr);

Si vous en avez besoin pour commencer à un, utilisez ce qui suit:

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

Voici les pages de manuel des fonctions utilisées:


1
Vous devez utiliser range (0, count ($ arr) - 1) pour obtenir un tableau indexé à zéro.
Max Hartshorn

C'est génial, vous pouvez également essayer d'utiliser array_unshift ($ arr, '') pour ajouter un élément à index zéro, puis unset ($ arr [0]) pour le supprimer, déplaçant ainsi tous les index de un. C'est peut-être plus rapide que array_combine (). Ou pas :)
Steve Horvath

Notez que array_valuesrenvoie une copie du tableau. Donc, si vous avez des références au tableau, ce array_spliceserait mieux. Voir la solution @imagiro.
Nux

Ne le array_values()faites fonctionner que si vous commencez avec l'index 0 tout le temps.
kishor10d

55

Voici le meilleur moyen :

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

qui retourne

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

en faisant cela

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

tu comprends ça

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

Explication

array_values() : Renvoie les valeurs du tableau d'entrée et les indexes numériquement.

array_filter(): Filtre les éléments d'un tableau avec une fonction définie par l'utilisateur (UDF si aucune n'est fournie , toutes les entrées de la table d'entrée valant FALSE seront supprimées .)


3
Si vous ne vous souciez pas de l'ordre, vous pouvez aussi simplement trier ($ array);
Peter M. Elias

array_filter()semble totalement sans rapport avec les données de l'échantillon.
mickmackusa le

13

Je viens de découvrir que tu peux aussi faire un

array_splice($ar, 0, 0);

Cela fait la réindexation en place, donc vous ne vous retrouvez pas avec une copie du tableau d'origine.


9

Pourquoi réindexer? Ajoutez simplement 1 à l'index:

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

Modifier Une    fois la question clarifiée: vous pouvez utiliser le array_valuespour réinitialiser l'index à partir de 0. Ensuite, vous pouvez utiliser l'algorithme ci-dessus si vous voulez juste que les éléments imprimés commencent à 1.


réponse sous-estimée à cette question :)
jminkler

6

Eh bien, j'aimerais penser que quel que soit votre objectif final, vous n'aurez pas besoin de modifier le tableau pour qu'il soit basé sur 1 plutôt que sur 0, mais vous pourriez plutôt le gérer au moment de l'itération, comme l'a publié Gumbo.

Cependant , pour répondre à votre question, cette fonction doit convertir n'importe quel tableau en une version basée sur 1

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

ÉDITER

Voici une fonction plus réutilisable / flexible, si vous le désirez

$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

Cela fera ce que vous voulez:

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

Vous voudrez peut-être vous demander pourquoi vous souhaitez utiliser un tableau basé sur 1. Les tableaux de base zéro (lors de l'utilisation de tableaux non associatifs) sont assez standard, et si vous souhaitez générer une sortie vers une interface utilisateur, la plupart géreraient la solution en augmentant simplement l'entier lors de la sortie vers l'interface utilisateur.

Pensez à la cohérence - à la fois dans votre application et dans le code avec lequel vous travaillez - lorsque vous pensez aux indexeurs basés sur 1 pour les tableaux.


2
Cela est directement corrélé à la séparation entre la couche de gestion et la couche de présentation. Si vous modifiez le code dans votre logique pour tenir compte de la présentation, vous faites de mauvaises choses. Par exemple, si vous avez fait cela pour un contrôleur, votre contrôleur est soudainement lié à un rendu de vue spécifique plutôt que de préparer les données pour le rendu de vue qu'il peut utiliser (php, json, xml, rss, etc.)
Tres

5

Une solution plus élégante:

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


6
Vous appelez cela élégant?
Julian

5

Vous pouvez réindexer un tableau pour que le nouveau tableau commence par un index de 1 comme ceci;

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

La sortie de ce qui précède est;

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

Vous n'êtes pas obligé d'utiliser array_valuesici. Voyez ma réponse.
Pluie

4

Similaire à @monowerker, j'avais besoin de réindexer un tableau en utilisant la clé d'un objet ...

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

Cela a abouti à:

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

Si vous n'essayez pas de réorganiser la baie, vous pouvez simplement faire:

$ tableau = tableau_reverse ($ tableau);
$ tableau = tableau_reverse ($ tableau);

Le array_reverse est très rapide et il se réorganise au fur et à mesure qu'il s'inverse. Quelqu'un d'autre m'a montré cela il y a longtemps. Je ne peux donc pas m'attribuer le mérite de l'avoir inventé. Mais c'est très simple et rapide.


2

Semblable à la contribution de Nick, je suis venu à la même solution pour réindexer un tableau, mais j'ai un peu amélioré la fonction car à partir de la version 5.4 de PHP, cela ne fonctionne pas à cause du passage de variables par référence. Un exemple de fonction de réindexation est alors comme ceci en utilisant la usefermeture de mot-clé:

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

1

Voici ma propre implémentation. Les clés du tableau d'entrée seront renumérotées avec des clés incrémentées à partir de $ 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

Faites simplement ceci:

<?php

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

1

Vous pouvez facilement le faire après avoir utilisé les fonctions array_values ​​() et array_filter () ensemble pour supprimer les éléments de tableau vides et réindexer un tableau en PHP.

Fonction array_filter () La fonction PHP array_filter () supprime les éléments de tableau vides ou les valeurs d'un tableau en PHP. Cela supprimera également les valeurs vides, nulles, fausses, 0 (zéro).

Fonction array_values ​​() La fonction PHP array_values ​​() renvoie un tableau contenant toutes les valeurs d'un tableau. Le tableau retourné aura des touches numériques, commençant à 0 et augmentées de 1.

Supprimer les éléments de tableau vides et réindexer

Voyons d'abord la sortie du tableau $ stack:

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

Production:

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

Dans la sortie ci-dessus, nous voulons supprimer les valeurs vides, nulles, 0 (zéro), puis réindexer les éléments du tableau. Nous allons maintenant utiliser les fonctions array_values ​​() et array_filter () ensemble comme dans l'exemple ci-dessous:

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

Production:

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

array_filter()semble totalement sans rapport avec les exemples de données du PO.
mickmackusa le

1

Dupliquer la suppression et réindexer un tableau:

<?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()semble totalement hors de propos pour les données d'échantillon du PO.
mickmackusa le

1

Le moyen le plus rapide auquel je puisse penser

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

Et si vous voulez juste réindexer le tableau (commencez à zéro) et que vous avez PHP +7.3, vous pouvez le faire de cette façon

array_unshift($arr);

Je crois que array_unshiftc'est mieux que array_valuescar le premier ne crée pas de copie du tableau.


0

On a l'impression que toutes les array_combine()réponses copient toutes la même «erreur» (l'appel inutile de array_values()).

array_combine() ignore les clés des deux paramètres qu'il reçoit.

Code: ( Démo )

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

Production:

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

Le tri est juste un tri () , la réindexation semble un peu ridicule mais si c'est nécessaire, cela le fera. Bien que pas en place. Utilisez array_walk () si vous voulez faire cela dans un tas d'endroits, utilisez simplement une boucle for-key-value s'il s'agit d'une opération ponctuelle.

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

Si vous pouvez créer un nouveau tableau, c'est ceci:

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

Si vous avez besoin d'une inversion sur place, vous devez exécuter à l'envers afin de ne pas piétiner les index dont vous avez besoin:

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

20
Toute réponse à ce problème ne devrait pas nécessiter de boucle. L'élément clé de la réponse consiste à utiliser array_values()pour obtenir un tableau basé sur 0, puis à ajuster ce résultat si un tableau basé sur 1 est vraiment nécessaire.
grantwparks
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.