Як перевстановити масив у PHP?


157

У мене є такий масив, який я хотів би перевстановити, щоб ключі були перевернені (в ідеалі починаючи з 1):

Поточний масив ( редагувати: масив насправді виглядає так):

Array (

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

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

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

)

Як має бути:

Array (

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

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

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

)

1
Де щось перевернуто?
Gumbo

Дивіться мою
редакцію

І навіщо вам потрібен індекс першого елемента 1? Просто форматування або для внутрішньої обробки?
Gumbo

Він буде використовуватися як парам для функції отримати URL-сегмент, щось на зразок get_url_segment (1) повернеться, наприклад, на цій сторінці "питання"
meleyal

Відповіді:


445

Якщо ви хочете переіндексувати, починаючи з нуля, просто виконайте наступне:

$iZero = array_values($arr);

Якщо вам потрібно запустити його одразу, скористайтеся наступним:

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

Ось сторінки керівництва щодо використовуваних функцій:


1
Ви повинні використовувати діапазон (0, count ($ arr) - 1), щоб ви отримали нульовий масив.
Макс Хартсхорн

Це чудово, або ви можете спробувати використовувати array_unshift ($ arr, ''), щоб додати нульовий індексований елемент, а потім скасувати ($ arr [0]), щоб видалити його, перемістивши таким чином усі індекси на одиницю. Це може бути швидше, ніж array_combine (). Або ні :)
Стів Хорват

Зверніть увагу, що array_valuesповертає копію масиву. Тож якщо у вас є посилання на масив, тоді array_spliceбуло б краще. Дивіться рішення @imagiro.
Nux

Працюйте лише array_values()тоді, якщо весь час починаєте з індексу 0.
kishor10d

55

Ось найкращий спосіб :

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

що повертається

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

роблячи це

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

ти це отримуєш

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

Пояснення

array_values() : Повертає значення вхідного масиву та індексує числово.

array_filter(): Фільтрує елементи масиву за допомогою визначеної користувачем функції (UDF. Якщо такої не передбачено , усі записи в таблиці вводу, що оцінюються FALSE, будуть видалені .)


3
Якщо ви не дбаєте про замовлення, ви також можете просто сортувати ($ масив);
Петро М. Ілля

array_filter()видається абсолютно невідповідним для даних вибірки.
mickmackusa

13

Я щойно з'ясував, що ви також можете зробити це

array_splice($ar, 0, 0);

Це означає, що повторна індексація не відбудеться, тому ви не отримаєте копію оригінального масиву.


9

Чому переіндексація? Просто додайте 1 до індексу:

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

Редагувати    Після уточнення питання: Ви можете скористатися array_valuesдля скидання індексу, починаючи з 0. Тоді ви можете використовувати алгоритм, описаний вище, якщо ви хочете, щоб надруковані елементи починалися з 1.


занижена відповідь на це питання :)
jminkler

6

Ну, я хотів би подумати, що для будь-якої вашої кінцевої мети вам насправді не потрібно буде змінювати масив на 1-базі на відміну від 0-бази, а натомість можна обробляти його під час ітерації, як опубліковано Gumbo.

Однак , щоб відповісти на ваше запитання, ця функція повинна перетворити будь-який масив у версію на основі 1

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

EDIT

Ось більш функціональна / гнучка функція, якщо ви цього хочете

$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

Це зробить те, що ви хочете:

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

Ви можете розглянути, для чого взагалі потрібно використовувати 1-базисний масив. Масиви на основі нуля (при використанні неасоціативних масивів) є досить стандартними, і якщо ви хочете виводити в інтерфейс, більшість буде обробляти рішення шляхом простого збільшення цілого числа при виході в інтерфейс.

Подумайте про послідовність - як у програмі, так і в коді, з яким ви працюєте -, думаючи про індексатори на основі масивів на основі 1.


2
Це безпосередньо корелює з поділом між бізнес-шаром та шаром презентації. Якщо ви змінюєте код у своїй логіці, щоб пристосувати презентацію, ви робите погані речі. Наприклад, якщо ви зробили це для контролера, раптом ваш контролер прив’язаний до конкретного візуалізатора перегляду, замість цього він готує дані для того, який рендер вигляд він може використовувати (php, json, xml, rss тощо)
Tres


5

Ви можете повторно встановити масив, щоб новий масив починався з індексу 1 подібного;

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

Вихід із зазначеного вище;

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

Тут не потрібно використовувати array_values. Дивіться мою відповідь.
Дощ

4

Подібно до @monowerker, мені потрібно було перевстановити масив за допомогою ключа об’єкта ...

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

Це призвело до:

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

Якщо ви не намагаєтесь змінити порядок масиву, ви можете просто зробити:

$ array = array_reverse ($ масив);
$ array = array_reverse ($ масив);

Реверсія array_reverse дуже швидка, і вона змінює порядок перетворення. Хтось ще мені це давно показав. Тому я не можу брати на себе кредит за те, що придумав це. Але це дуже просто і швидко.


2

Подібно до вкладу Ніка, я прийшов до того ж рішення щодо перенастроювання масиву, але трохи покращив функцію, оскільки з PHP версії 5.4 він не працює через передачу змінних за посиланням. Приклад функції повторного детексування виглядає таким чином за допомогою useзакриття ключового слова:

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

1

Ось моя власна реалізація. Клавіші вхідного масиву будуть перенумеровані з збільшенням ключів, починаючи з $ 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

Ви можете легко зробити це після використання функції array_values ​​() та array_filter () разом для видалення порожніх елементів масиву та повторного вилучення з масиву в PHP.

Функція array_filter () Функція PHP array_filter () видаляє порожні елементи масиву або значення з масиву в PHP. Це також видалить порожні, null, false, 0 (нульові) значення.

array_values ​​() функція Функція PHP array_values ​​() повертає масив, що містить усі значення масиву. Повернутий масив матиме цифрові клавіші, починаючи з 0 і збільшуючись на 1.

Видаліть елементи порожнього масиву та Reindex

Спершу давайте подивимось вихід масиву $ stack:

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

Вихід:

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

З наведеного вище висновку ми хочемо видалити порожні, нульові, 0 (нульові) значення, а потім перевстановити елементи масиву. Тепер ми будемо використовувати функції array_values ​​() та array_filter () разом, як у наведеному нижче прикладі:

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

Вихід:

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

array_filter()видається абсолютно невідповідним для вибіркових даних ОП.
mickmackusa

1

Повторне видалення та повторне встановлення масиву

<?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()видається абсолютно невідповідним для вибіркових даних ОП.
mickmackusa

1

Найшвидший спосіб, про який я можу придумати

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

І якщо ви просто хочете перевстановити масив (початок з нуля) і у вас PHP +7.3, ви можете зробити це таким чином

array_unshift($arr);

Я вважаю array_unshift, що краще, ніж array_valuesколишній не створює копію масиву.


0

Складається враження, що всі array_combine()відповіді копіюють ту саму «помилку» (непотрібний дзвінок array_values()).

array_combine() ігнорує ключі обох параметрів, які він отримує.

Код: ( Демо )

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

Вихід:

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

Сортування - це лише різновид () , перевстановлення здається трохи нерозумним, але якщо це потрібно, це зробимо. Хоч і не на місці. Використовуйте array_walk (), якщо ви будете робити це у купі місць, просто використовуйте цикл for-key-value, якщо це разова операція.

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

Якщо добре створити новий масив, це:

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

Якщо вам потрібен переворот на місці, вам потрібно запуститись назад, щоб не тупати за потрібними індексами:

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

20
Будь-яка відповідь на цю проблему не повинна потребувати циклу. Ключова частина відповіді використовується array_values()для отримання масиву на основі 0, а потім певного коригування цього результату, якщо дійсно потрібен масив на основі 1 .
grantwparks
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.