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

)
Meleyal
la source
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:

Andrew Moore
la source
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 .)

Sandra
la source
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.

imagiro
la source
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.

Gombo
la source
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 ) );
}
Peter Bailey
la source
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 ) 

?>
Greg
la source
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.

Michael Trausch
la source
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));

Ionuţ Pleşca
la source
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
)
Nigel Alderton
la source
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
        )
)
pseudo
la source
3
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;
Tom Haigh
la source
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.

marque
la source
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;
}
FantomX1
la source
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);
}
Mustapha Hadid
la source
1

Faites simplement ceci:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);
Roham Rafii
la source
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
)
Étoile
la source
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);
?>
Sam T
la source
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.

Pluie
la source
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,
  ),
)
Mickmackusa
la source
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 )

?>
monowerker
la source
-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
Jason Cohen
la source
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