Wie indiziere ich ein Array in PHP neu?

156

Ich habe das folgende Array, das ich neu indizieren möchte, damit die Schlüssel vertauscht werden (idealerweise ab 1):

Aktuelles Array ( Bearbeiten: Das Array sieht tatsächlich so aus):

Array (

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

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

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

)

Wie es sein sollte:

Array (

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

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

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

)
meleyal
quelle
1
Wo ist etwas umgekehrt?
Gumbo
Siehe meine Bearbeitung zum ersten Beispiel
meleyal
Und warum muss der Index des ersten Elements 1 sein? Nur eine Formatangelegenheit oder für die interne Verarbeitung?
Gumbo
Es wird als Parameter für eine Funktion verwendet, um das URL-Segment abzurufen. So etwas wie get_url_segment (1) würde zB auf dieser Seite "Fragen" zurückgeben
meleyal

Antworten:

444

Wenn Sie ab Null neu indizieren möchten, gehen Sie einfach wie folgt vor:

$iZero = array_values($arr);

Wenn Sie es benötigen, um um eins zu beginnen, verwenden Sie Folgendes:

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

Hier sind die Handbuchseiten für die verwendeten Funktionen:

Andrew Moore
quelle
1
Sie sollten den Bereich (0, count ($ arr) - 1) verwenden, damit Sie ein Array mit null Index erhalten.
Max Hartshorn
Es ist großartig, alternativ können Sie versuchen, mit array_unshift ($ arr, '') ein Element mit Nullindex hinzuzufügen, und dann ($ arr [0]) deaktivieren, um es zu entfernen, wodurch alle Indizes um eins nach oben verschoben werden. Es ist vielleicht schneller als array_combine (). Oder nicht :)
Steve Horvath
Beachten Sie, dass array_valueseine Kopie des Arrays zurückgegeben wird. Wenn Sie also Verweise auf das Array haben, ist array_splicedies besser. Siehe @ imagiro-Lösung.
Nux
Nur array_values()damit es funktioniert, wenn Sie mit dem Index 0 die ganze Zeit starten.
kishor10d
55

Hier ist der beste Weg :

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

das kehrt zurück

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

auf diese Weise

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

Du bekommst das

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

Erläuterung

array_values() : Gibt die Werte des Eingabearrays und der Indizes numerisch zurück.

array_filter(): Filtert die Elemente eines Arrays mit einer benutzerdefinierten Funktion (UDF Wenn keine angegeben ist , werden alle Einträge in der Eingabetabelle mit dem Wert FALSE gelöscht .)

Sandra
quelle
3
Wenn Sie sich nicht für die Reihenfolge interessieren, können Sie auch einfach sortieren ($ array);
Peter M. Elias
array_filter()scheint für die Beispieldaten völlig irrelevant.
Mickmackusa
13

Ich habe gerade herausgefunden, dass du auch eine machen kannst

array_splice($ar, 0, 0);

Dadurch wird die Neuindizierung an Ort und Stelle durchgeführt, sodass Sie keine Kopie des ursprünglichen Arrays erhalten.

imagiro
quelle
9

Warum neu indizieren? Fügen Sie einfach 1 zum Index hinzu:

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

Bearbeiten    Nachdem die Frage geklärt wurde: Sie können array_valuesden Index mit 0 ab 0 zurücksetzen. Dann können Sie den obigen Algorithmus verwenden, wenn Sie nur möchten, dass gedruckte Elemente bei 1 beginnen.

Gumbo
quelle
unterschätzte Antwort auf diese Frage :)
jminkler
6

Nun, ich würde gerne denken, dass Sie das Array für Ihr Endziel nicht so ändern müssten, dass es 1-basiert und nicht 0-basiert ist, sondern es stattdessen zur Iterationszeit wie von Gumbo veröffentlicht behandeln könnten.

Um Ihre Frage zu beantworten, sollte diese Funktion jedoch jedes Array in eine 1-basierte Version konvertieren

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

BEARBEITEN

Hier ist eine wiederverwendbarere / flexiblere Funktion, falls Sie dies wünschen

$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
quelle
5

Dies wird tun, was Sie wollen:

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

Möglicherweise möchten Sie überlegen, warum Sie überhaupt ein 1-basiertes Array verwenden möchten. Nullbasierte Arrays (bei Verwendung nicht assoziativer Arrays) sind Standard, und wenn Sie auf einer Benutzeroberfläche ausgeben möchten, würden die meisten die Lösung handhaben, indem sie bei der Ausgabe auf der Benutzeroberfläche nur die Ganzzahl erhöhen.

Denken Sie an die Konsistenz - sowohl in Ihrer Anwendung als auch in dem Code, mit dem Sie arbeiten -, wenn Sie an 1-basierte Indexer für Arrays denken.

Michael Trausch
quelle
2
Dies korreliert direkt mit der Trennung zwischen Geschäftsschicht und Präsentationsschicht. Wenn Sie Code in Ihrer Logik ändern, um die Präsentation zu ermöglichen, tun Sie schlechte Dinge. Wenn Sie dies beispielsweise für einen Controller getan haben, ist Ihr Controller plötzlich an einen bestimmten Ansichtsrenderer gebunden und bereitet Daten für den von ihm verwendeten Ansichtsrenderer vor (PHP, JSON, XML, RSS usw.)
Tres
5

Eine elegantere Lösung:

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

Ionuţ Pleşca
quelle
6
Du nennst das elegant?
Julian
5

Sie können ein Array neu indizieren, sodass das neue Array mit einem Index von 1 wie diesem beginnt.

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

Die Ausgabe von oben ist;

Array
(
    [2] => red
    [1] => green
    [0] => blue
)
Array
(
    [1] => red
    [2] => green
    [3] => blue
)
Nigel Alderton
quelle
Sie müssen hier nicht verwenden array_values. Siehe meine Antwort.
Regen
4

Ähnlich wie bei @monowerker musste ich ein Array mit dem Schlüssel eines Objekts neu indizieren ...

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

Dies führte zu:

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
quelle
3
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;
Tom Haigh
quelle
3

Wenn Sie nicht versuchen, das Array neu zu ordnen, können Sie einfach Folgendes tun:

$ array = array_reverse ($ array);
$ array = array_reverse ($ array);

Das array_reverse ist sehr schnell und ordnet es beim Umkehren neu. Jemand anderes hat mir das vor langer Zeit gezeigt. Ich kann es mir also nicht vorstellen, dass ich es mir ausgedacht habe. Aber es ist sehr einfach und schnell.

Kennzeichen
quelle
2

Ähnlich wie in Nicks Beitrag kam ich zu derselben Lösung für die Neuindizierung eines Arrays, verbesserte jedoch die Funktion ein wenig, da sie ab PHP Version 5.4 nicht funktioniert, da Variablen als Referenz übergeben werden. Die Beispielfunktion für die Neuindizierung ist dann wie folgt use: Verwenden des Schlüsselwortschlusses:

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

Hier ist meine eigene Implementierung. Die Schlüssel im Eingabearray werden mit inkrementierenden Schlüsseln ab $ start_index neu nummeriert.

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
quelle
1

Mach das einfach:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);
Roham Rafii
quelle
1

Sie können dies einfach tun, nachdem Sie die Funktionen array_values ​​() und array_filter () zusammen verwendet haben, um leere Array-Elemente zu entfernen und aus einem Array in PHP neu zu indizieren.

array_filter () -Funktion Die PHP- Funktion array_filter () entfernt leere Array-Elemente oder -Werte aus einem Array in PHP. Dadurch werden auch leere, null, falsche, 0 (Null) Werte entfernt.

array_values ​​() -Funktion Die PHP- Funktion array_values ​​() gibt ein Array zurück, das alle Werte eines Arrays enthält. Das zurückgegebene Array verfügt über Zifferntasten, die bei 0 beginnen und um 1 erhöht werden.

Entfernen Sie leere Array-Elemente und indizieren Sie sie neu

Schauen wir uns zuerst die Ausgabe des $ stack-Arrays an:

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

Ausgabe:

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

In der obigen Ausgabe möchten wir leere, null, 0 (null) Werte entfernen und dann Array-Elemente neu indizieren. Jetzt verwenden wir die Funktionen array_values ​​() und array_filter () zusammen wie im folgenden Beispiel:

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

Ausgabe:

Array
(
    [0] => PHP
    [1] => HTML
    [2] => CSS
    [3] => JavaScript
)
Star
quelle
array_filter()scheint für die Beispieldaten des OP völlig irrelevant zu sein.
Mickmackusa
1

Doppelte Entfernung und Neuindizierung eines Arrays:

<?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.
quelle
array_filter()scheint für die Beispieldaten des OP völlig irrelevant zu sein.
Mickmackusa
1

Der schnellste Weg, den ich mir vorstellen kann

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

Und wenn Sie das Array nur neu indizieren möchten (beginnen Sie bei Null) und PHP +7.3 haben, können Sie dies auf diese Weise tun

array_unshift($arr);

Ich glaube, es array_unshiftist besser als, array_valuesda erstere keine Kopie des Arrays erstellt.

Regen
quelle
0

Es fühlt sich so an, als würden alle array_combine()Antworten denselben "Fehler" (den unnötigen Aufruf von array_values()) kopieren .

array_combine() ignoriert die Schlüssel beider empfangenen Parameter.

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

Ausgabe:

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
quelle
0

Sortieren ist nur eine Sortierung () , Neuindizierung scheint ein bisschen albern, aber wenn es benötigt wird, wird es dies tun. Obwohl nicht vorhanden. Verwenden Sie array_walk (), wenn Sie dies an mehreren Stellen tun möchten. Verwenden Sie einfach eine for-key-value-Schleife, wenn dies eine einmalige Operation ist.

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

Wenn es in Ordnung ist, ein neues Array zu erstellen, ist dies:

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

Wenn Sie eine Umkehrung an Ort und Stelle benötigen, müssen Sie rückwärts laufen, damit Sie nicht auf die benötigten Indizes stampfen:

for ( $k = count($array) ; $k-- > 0 ; )
    $result[ $k+1 ] = $result[ $k ];
unset( $array[0] );   // remove the "zero" element
Jason Cohen
quelle
20
Jede Antwort auf dieses Problem sollte keine Schleife benötigen. Der Hauptteil der Antwort besteht array_values()darin, ein 0-basiertes Array zu erhalten und dieses Ergebnis dann anzupassen, wenn ein 1-basiertes Array wirklich erforderlich ist.
Grantwparks