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

)

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:


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


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.


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.


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

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 ) 

?>

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.


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


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
)

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

3
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;

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.


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

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

1

Po prostu zrób to:

<?php

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

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
)

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

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.


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

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 )

?>

-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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.