Jak reindeksować tablicę w PHP?

157

Mam następującą tablicę, którą chciałbym ponownie zindeksować, aby klucze były odwrócone (najlepiej zaczynając od 1):

Bieżąca tablica ( edytuj: tablica faktycznie wygląda tak):

Array (

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

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

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

)

Jak powinno być:

Array (

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

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

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

)
meleyal
źródło
1
Gdzie jest coś odwróconego?
Gumbo
Zobacz moją edycję pierwszego przykładu
meleyal
Dlaczego potrzebujesz indeksu pierwszego elementu równego 1? Tylko kwestia formatu czy do wewnętrznego przetwarzania?
Gumbo
Będzie użyty jako parametr funkcji pobierającej segment adresu URL, coś takiego jak get_url_segment (1) zwróci np. Na tej stronie "pytania"
meleyal

Odpowiedzi:

445

Jeśli chcesz ponownie indeksować zaczynając od zera, po prostu wykonaj następujące czynności:

$iZero = array_values($arr);

Jeśli potrzebujesz go, aby zacząć od pierwszego, użyj następujących:

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

Oto strony podręcznika dotyczące używanych funkcji:

Andrew Moore
źródło
1
Powinieneś użyć range (0, count ($ arr) - 1), aby otrzymać tablicę indeksowaną przez zero.
Max Hartshorn
To świetnie, alternatywnie możesz spróbować użyć array_unshift ($ arr, ''), aby dodać element indeksowany przez zero, a następnie cofnąć ustawienie ($ arr [0]), aby go usunąć, przesuwając w ten sposób wszystkie indeksy o jeden w górę. Może być szybsze niż array_combine (). Albo nie :)
Steve Horvath
Zauważ, że array_valueszwraca kopię tablicy. Więc jeśli masz odniesienia do tablicy, array_splicebyłoby lepiej. Zobacz rozwiązanie @imagiro.
Nux
Spraw, array_values()by działało tylko wtedy, gdy cały czas zaczynasz od indeksu 0.
kishor10d
55

Oto najlepszy sposób :

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

to wraca

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

robiąc to

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

masz to

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

Wyjaśnienie

array_values() : Zwraca wartości tablicy wejściowej i indeksuje liczbowo.

array_filter(): Filtruje elementy tablicy za pomocą funkcji zdefiniowanej przez użytkownika (UDF Jeśli żadna nie zostanie podana , wszystkie wpisy w tabeli wejściowej o wartości FALSE zostaną usunięte ).

Sandra
źródło
3
Jeśli nie zależy Ci na porządku, możesz po prostu posortować ($ tablica);
Peter M. Elias
array_filter()wydaje się zupełnie nieistotne dla przykładowych danych.
mickmackusa
13

Właśnie się dowiedziałem, że możesz też zrobić

array_splice($ar, 0, 0);

To powoduje ponowne indeksowanie w miejscu, więc nie otrzymasz kopii oryginalnej tablicy.

imagiro
źródło
9

Po co reindeksować? Po prostu dodaj 1 do indeksu:

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

Edytuj    Po wyjaśnieniu pytania: Możesz użyć array_valuesdo zresetowania indeksu, zaczynając od 0. Następnie możesz użyć powyższego algorytmu, jeśli chcesz, aby wydrukowane elementy zaczynały się od 1.

Gumbo
źródło
niedoceniana odpowiedź na to pytanie :)
jminkler
6

Cóż, chciałbym pomyśleć, że bez względu na cel końcowy nie musiałbyś modyfikować tablicy tak, aby była oparta na 1, a nie na 0, ale zamiast tego mógłbyś sobie z tym poradzić w czasie iteracji, jak opublikował Gumbo.

Jednak aby odpowiedzieć na twoje pytanie, ta funkcja powinna przekonwertować dowolną tablicę na wersję opartą na 1

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

EDYTOWAĆ

Oto bardziej elastyczna / wielokrotnego użytku funkcja, jeśli sobie tego życzysz

$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
źródło
5

To zrobi, co chcesz:

<?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
źródło
5

Możesz rozważyć, dlaczego w ogóle chcesz używać tablicy opartej na 1. Tablice oparte na zerach (w przypadku korzystania z tablic niezasocjacyjnych) są dość standardowe, a jeśli chcesz wyświetlać dane wyjściowe do interfejsu użytkownika, większość z nich poradzi sobie z rozwiązaniem, po prostu zwiększając liczbę całkowitą po wyjściu do interfejsu użytkownika.

Pomyśl o spójności - zarówno w aplikacji, jak iw kodzie, z którym pracujesz - myśląc o indeksatorach opartych na 1 dla tablic.

Michael Trausch
źródło
2
Ma to bezpośredni związek z oddzieleniem warstwy biznesowej od warstwy prezentacji. Jeśli modyfikujesz kod w swojej logice, aby dostosować go do prezentacji, robisz złe rzeczy. Na przykład, jeśli zrobiłeś to dla kontrolera, nagle twój kontroler jest powiązany z określonym rendererem widoku, zamiast przygotowywać dane dla dowolnego renderera widoku, którego może używać (php, json, xml, rss itp.)
Tres
5

Bardziej eleganckie rozwiązanie:

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

Ionuţ Pleşca
źródło
6
Nazywasz to eleganckim?
Julian
5

Możesz ponownie zindeksować tablicę, aby nowa tablica zaczynała się od indeksu równego 1 w ten sposób;

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

Wynik z powyższego to;

Array
(
    [2] => red
    [1] => green
    [0] => blue
)
Array
(
    [1] => red
    [2] => green
    [3] => blue
)
Nigel Alderton
źródło
Nie musisz array_valuestutaj używać . Zobacz moją odpowiedź.
Deszcz
4

Podobnie jak @monowerker, musiałem ponownie zindeksować tablicę za pomocą klucza obiektu ...

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

Spowodowało to:

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
        )
)
Nacięcie
źródło
3
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;
Tom Haigh
źródło
3

Jeśli nie próbujesz zmienić kolejności tablicy, możesz po prostu zrobić:

$ tablica = tablica_reverse ($ tablica);
$ tablica = tablica_reverse ($ tablica);

Funkcja array_reverse jest bardzo szybka i zmienia kolejność podczas odwracania. Ktoś inny pokazał mi to dawno temu. Więc nie mogę przypisać sobie zasługi za wymyślenie tego. Ale to jest bardzo proste i szybkie.

znak
źródło
2

Podobnie jak w przypadku wkładu Nicka, doszedłem do tego samego rozwiązania do ponownego indeksowania tablicy, ale ulepszyłem nieco tę funkcję, ponieważ od wersji PHP 5.4 nie działa z powodu przekazywania zmiennych przez odniesienie. Przykładowa funkcja reindeksowania wygląda więc tak, jak ta przy użyciu usezamknięcia słowa kluczowego:

function indexArrayByElement($array, $element)
{
    $arrayReindexed = [];
    array_walk(
        $array,
        function ($item, $key) use (&$arrayReindexed, $element) {
            $arrayReindexed[$item[$element]] = $item;
        }
    );
    return $arrayReindexed;
}
FantomX1
źródło
1

Oto moja własna realizacja. Klucze w tablicy wejściowej zostaną ponumerowane kluczami zwiększającymi się, zaczynając od $ 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
źródło
1

Po prostu zrób to:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);
Roham Rafii
źródło
1

Możesz to łatwo zrobić po połączeniu funkcji array_values ​​() i array_filter (), aby usunąć puste elementy tablicy i ponownie zindeksować tablicę w PHP.

Funkcja array_filter () Funkcja PHP array_filter () usuwa puste elementy tablicy lub wartości z tablicy w PHP. Spowoduje to również usunięcie wartości pustych, null, false, 0 (zero).

Funkcja array_values ​​() Funkcja PHP array_values ​​() zwraca tablicę zawierającą wszystkie wartości tablicy. Zwrócona tablica będzie zawierała klucze numeryczne, zaczynając od 0 i zwiększając o 1.

Usuń puste elementy tablicy i ponownie zindeksuj

Najpierw zobaczmy wynik tablicy $ stack:

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

Wynik:

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

W powyższym wyjściu chcemy usunąć puste, null, 0 (zero) wartości, a następnie ponownie zindeksować elementy tablicy. Teraz użyjemy funkcji array_values ​​() i array_filter (), jak w poniższym przykładzie:

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

Wynik:

Array
(
    [0] => PHP
    [1] => HTML
    [2] => CSS
    [3] => JavaScript
)
Gwiazda
źródło
array_filter()wydaje się zupełnie nieistotny dla przykładowych danych PO.
mickmackusa
1

Zduplikowane usunięcie i ponowne zindeksowanie tablicy:

<?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
źródło
array_filter()wydaje się zupełnie nieistotny dla przykładowych danych PO.
mickmackusa
1

Najszybszy sposób, jaki przychodzi mi do głowy

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

A jeśli chcesz tylko ponownie zindeksować tablicę (zacznij od zera) i masz PHP +7.3, możesz to zrobić w ten sposób

array_unshift($arr);

Uważam, że array_unshiftjest lepszy niż array_valuesten, który nie tworzy kopii tablicy.

Deszcz
źródło
0

Wydaje się, że wszystkie array_combine()odpowiedzi kopiują ten sam „błąd” (niepotrzebne wezwanie array_values()).

array_combine() ignoruje klucze obu parametrów, które otrzymuje.

Kod: ( 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));

Wynik:

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
źródło
0

Sortowanie to po prostu sort () , ponowne zindeksowanie wydaje się trochę głupie, ale jeśli zajdzie taka potrzeba, wystarczy. Chociaż nie na miejscu. Użyj funkcji array_walk (), jeśli będziesz to robić w kilku miejscach, po prostu użyj pętli for-klucz-wartość, jeśli jest to operacja jednorazowa.

<?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
źródło
-10

Jeśli można utworzyć nową tablicę, to jest to:

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

Jeśli potrzebujesz odwrócenia w miejscu, musisz działać wstecz, aby nie tupać na indeksach, których potrzebujesz:

for ( $k = count($array) ; $k-- > 0 ; )
    $result[ $k+1 ] = $result[ $k ];
unset( $array[0] );   // remove the "zero" element
Jason Cohen
źródło
20
Żadna odpowiedź na ten problem nie powinna wymagać pętli. Kluczową częścią odpowiedzi jest użycie array_values()do uzyskania tablicy opartej na 0, a następnie dokonanie pewnych korekt tego wyniku, jeśli tablica oparta na 1 jest naprawdę wymagana.
grantwparks