Как вы переиндексировать массив в 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] => 
    )

)
meleyal
источник
1
Где там что-то поменялось?
Гамбо
См. Мое изменение к первому примеру
meleyal
И зачем вам индекс первого элемента 1? Просто формат имеет значение или для внутренней обработки?
Гамбо
Он будет использоваться в качестве параметра для функции, чтобы получить сегмент url, что-то вроде get_url_segment (1) вернет, например, на этой странице «questions»
meleyal

Ответы:

445

Если вы хотите переиндексировать, начиная с нуля, просто сделайте следующее:

$iZero = array_values($arr);

Если вам нужно, чтобы начать с одного, то используйте следующее:

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

Вот справочные страницы для используемых функций:

Эндрю Мур
источник
1
Вы должны использовать range (0, count ($ arr) - 1), чтобы получить массив с нулевым индексом.
Макс Хартсхорн
Это замечательно, в качестве альтернативы вы можете попробовать использовать array_unshift ($ arr, ''), чтобы добавить элемент с нулевым индексом, а затем удалить его ($ arr [0]), чтобы переместить все индексы на один. Это может быть быстрее, чем array_combine (). Или нет :)
Стив Хорват
Обратите внимание, что array_valuesвозвращает копию массива. Так что, если у вас есть ссылки на массив, array_spliceбыло бы лучше. Смотрите решение @imagiro.
Nux
Заставьте array_values()его работать, если вы все время начинаете с индекса 0.
Кишор10д
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 будут удалены .)

Sandra
источник
3
Если вам не важен порядок, вы также можете просто отсортировать ($ array);
Питер М. Элиас
array_filter()кажется совершенно не относящимся к данным выборки.
mickmackusa
13

Я только что узнал, что вы также можете сделать

array_splice($ar, 0, 0);

Это делает реиндексацию на месте, так что вы не получите копию исходного массива.

imagiro
источник
9

Почему переиндексация? Просто добавьте 1 к индексу:

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

Редактировать    После того, как вопрос прояснен: вы можете использовать array_valuesдля сброса индекса, начиная с 0. Затем вы можете использовать алгоритм выше, если вы просто хотите, чтобы напечатанные элементы начинались с 1.

гумбо
источник
недооцененный ответ на этот вопрос :)
Jminkler
6

Что ж, я хотел бы думать, что для любой вашей конечной цели вам на самом деле не нужно изменять массив, чтобы он был основан на 1, а не на 0, но вместо этого мог бы обрабатывать его во время итерации, как написал Гамбо.

Однако , чтобы ответить на ваш вопрос, эта функция должна преобразовать любой массив в версию на основе 1

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

РЕДАКТИРОВАТЬ

Вот более многоразовая / гибкая функция, если хотите

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

?>
Greg
источник
5

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

Подумайте о согласованности - как в вашем приложении, так и в коде, с которым вы работаете, - когда думаете об основанных на 1 индексаторах для массивов.

Майкл Трауш
источник
2
Это напрямую связано с разделением между бизнес-уровнем и уровнем представления. Если вы изменяете код в своей логике для приспособления к презентации, вы делаете плохие вещи. Например, если вы сделали это для контроллера, ваш контроллер внезапно привязывается к определенному представлению представления, а скорее готовит данные для любого средства визуализации представления, которое он может использовать (php, json, xml, rss и т. Д.)
Tres
5

Более элегантное решение:

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

Ionuţ Pleşca
источник
6
Вы называете это элегантным?
Джулиан
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
$tmp = array();
foreach (array_values($array) as $key => $value) {
    $tmp[$key+1] = $value;
}
$array = $tmp;
Том Хей
источник
3

Если вы не пытаетесь переупорядочить массив, вы можете просто сделать:

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

Массив 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;
}
FantomX1
источник
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

Просто сделайте это:

<?php

array_push($array, '');
$array = array_reverse($array);
array_shift($array);
Рохам Рафи
источник
1

Вы можете легко сделать это после совместного использования функций array_values ​​() и array_filter () для удаления пустых элементов массива и переиндексации из массива в PHP.

Функция array_filter () Функция PHP array_filter () удаляет пустые элементы массива или значения из массива в PHP. Это также удалит пустые, нулевые, ложные, 0 (ноль) значения.

Функция array_values ​​() Функция PHP array_values ​​() возвращает массив, содержащий все значения массива. Возвращенный массив будет иметь числовые ключи, начиная с 0 и увеличиваясь на 1.

Удалить пустые элементы массива и переиндексировать

Сначала давайте посмотрим на вывод массива $ 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,
  ),
)
mickmackusa
источник
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 )

?>
monowerker
источник
-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