Вставить новый элемент в массив в любой позиции в PHP

332

Как я могу вставить новый элемент в массив в любой позиции, например, в середине массива?

Теги:
arrays
insert

15 ответов

622
Лучший ответ

Вы можете найти это немного интуитивно понятным. Для этого требуется только один вызов функции array_splice:

$original = array( 'a', 'b', 'c', 'd', 'e' );
$inserted = array( 'x' ); // Not necessarily an array

array_splice( $original, 3, 0, $inserted ); // splice in at position 3
// $original is now a b c x d e
  • 21
    Странно, что такая базовая функциональность на самом деле в некотором роде скрыта, так как основное назначение этой функции, как описано в документации, это нечто иное (замена содержимого в массивах). Да, это указано в разделе аргументов, но если вы просто сканируете описания функций, чтобы найти, что использовать для вставки в массивы, вы бы никогда не нашли его.
  • 18
    Просто скажу, что это не сохранит ключи во $inserted массиве.
Показать ещё 5 комментариев
33

Функция, которая может вставляться как в целые, так и в строковые позиции:

/**
 * @param array      $array
 * @param int|string $position
 * @param mixed      $insert
 */
function array_insert(&$array, $position, $insert)
{
    if (is_int($position)) {
        array_splice($array, $position, 0, $insert);
    } else {
        $pos   = array_search($position, array_keys($array));
        $array = array_merge(
            array_slice($array, 0, $pos),
            $insert,
            array_slice($array, $pos)
        );
    }
}

Целое использование:

$arr = ["one", "two", "three"];
array_insert(
    $arr,
    1,
    "one-half"
);
// ->
array (
  0 => 'one',
  1 => 'one-half',
  2 => 'two',
  3 => 'three',
)

Использование строки:

$arr = [
    "name"  => [
        "type"      => "string",
        "maxlength" => "30",
    ],
    "email" => [
        "type"      => "email",
        "maxlength" => "150",
    ],
];

array_insert(
    $arr,
    "email",
    [
        "phone" => [
            "type"   => "string",
            "format" => "phone",
        ],
    ]
);
// ->
array (
  'name' =>
  array (
    'type' => 'string',
    'maxlength' => '30',
  ),
  'phone' =>
  array (
    'type' => 'string',
    'format' => 'phone',
  ),
  'email' =>
  array (
    'type' => 'email',
    'maxlength' => '150',
  ),
)
  • 2
    Отличное решение для int и позиции строки :)
  • 0
    array_splice() теряет ключи, а array_merge() - нет. Таким образом, результаты первой функции могут быть очень удивительными ... Тем более, что если у вас есть два элемента с одинаковым ключом, сохраняется только значение последнего ...
19
$a = array(1, 2, 3, 4);
$b = array_merge(array_slice($a, 0, 2), array(5), array_slice($a, 2));
// $b = array(1, 2, 5, 3, 4)
  • 8
    Использование + вместо array_merge может сохранить ключи
  • 0
    Теперь я могу добавить больше элементов перед индексом
3

Нет встроенной функции PHP (что я знаю), которая может делать именно то, что вы просили.

Я написал два метода, которые, я считаю, подходят для цели:

function insertBefore($input, $index, $element) {
    if (!array_key_exists($index, $input)) {
        throw new Exception("Index not found");
    }
    $tmpArray = array();
    $originalIndex = 0;
    foreach ($input as $key => $value) {
        if ($key === $index) {
            $tmpArray[] = $element;
            break;
        }
        $tmpArray[$key] = $value;
        $originalIndex++;
    }
    array_splice($input, 0, $originalIndex, $tmpArray);
    return $input;
}

function insertAfter($input, $index, $element) {
    if (!array_key_exists($index, $input)) {
        throw new Exception("Index not found");
    }
    $tmpArray = array();
    $originalIndex = 0;
    foreach ($input as $key => $value) {
        $tmpArray[$key] = $value;
        $originalIndex++;
        if ($key === $index) {
            $tmpArray[] = $element;
            break;
        }
    }
    array_splice($input, 0, $originalIndex, $tmpArray);
    return $input;
}

Хотя быстрая и, вероятно, более эффективная память, это действительно реально, когда нет необходимости поддерживать ключи массива.

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

function insertBefore($input, $index, $newKey, $element) {
    if (!array_key_exists($index, $input)) {
        throw new Exception("Index not found");
    }
    $tmpArray = array();
    foreach ($input as $key => $value) {
        if ($key === $index) {
            $tmpArray[$newKey] = $element;
        }
        $tmpArray[$key] = $value;
    }
    return $input;
}

function insertAfter($input, $index, $newKey, $element) {
    if (!array_key_exists($index, $input)) {
        throw new Exception("Index not found");
    }
    $tmpArray = array();
    foreach ($input as $key => $value) {
        $tmpArray[$key] = $value;
        if ($key === $index) {
            $tmpArray[$newKey] = $element;
        }
    }
    return $tmpArray;
}
  • 1
    Это отлично работает. Однако во втором примере в вашей функции insertBefore() вы должны вернуть $tmpArray вместо $input .
3

Таким образом вы можете вставлять массивы:

function array_insert(&$array, $value, $index)
{
    return $array = array_merge(array_splice($array, max(0, $index - 1)), array($value), $array);
}
  • 0
    Эта функция не сохраняет порядок в массиве.
1

Вы можете использовать этот

foreach ($array as $key => $value) 
{
    if($key==1)
    {
        $new_array[]=$other_array;
    }   
    $new_array[]=$value;    
}
0

Решение jay.lee является совершенным. Если вы хотите добавить элемент в многомерный массив, сначала добавьте одномерный массив, а затем замените его потом.

$original = (
[0] => Array
    (
        [title] => Speed
        [width] => 14
    )

[1] => Array
    (
        [title] => Date
        [width] => 18
    )

[2] => Array
    (
        [title] => Pineapple
        [width] => 30
     )
)

Добавление элемента в том же формате в этот массив добавит все новые индексы массива как элементы, а не только элементы.

$new = array(
    'title' => 'Time',
    'width' => 10
);
array_splice($original,1,0,array('random_string')); // can be more items
$original[1] = $new;  // replaced with actual item

Примечание. Добавление элементов непосредственно в многомерный массив с array_splice добавит все его индексы в качестве элементов, а не просто этот пункт.

0

Попробуйте следующее:

$colors = array('red', 'blue', 'yellow');

$colors = insertElementToArray($colors, 'green', 2);


function insertElementToArray($arr = array(), $element = null, $index = 0)
{
    if ($element == null) {
        return $arr;
    }

    $arrLength = count($arr);
    $j = $arrLength - 1;

    while ($j >= $index) {
        $arr[$j+1] = $arr[$j];
        $j--;
    }

    $arr[$index] = $element;

    return $arr;
}
0

если не уверены, то НЕ ДОЛЖНЫ ИСПОЛЬЗОВАТЬ ЭТИ:

$arr1 = $arr1 + $arr2;

ИЛИ

$arr1 += $arr2;

поскольку исходный массив + будет перезаписан. (см. источник)

0

Основываясь на отличном ответе @Halil, вот простая функция, как вставить новый элемент после определенного ключа, сохраняя целые ключи:

private function arrayInsertAfterKey($array, $afterKey, $key, $value){
    $pos   = array_search($afterKey, array_keys($array));

    return array_merge(
        array_slice($array, 0, $pos, $preserve_keys = true),
        array($key=>$value),
        array_slice($array, $pos, $preserve_keys = true)
    );
} 
0

Это также рабочее решение:

function array_insert(&$array,$element,$position=null) {
  if (count($array) == 0) {
    $array[] = $element;
  }
  elseif (is_numeric($position) && $position < 0) {
    if((count($array)+position) < 0) {
      $array = array_insert($array,$element,0);
    }
    else {
      $array[count($array)+$position] = $element;
    }
  }
  elseif (is_numeric($position) && isset($array[$position])) {
    $part1 = array_slice($array,0,$position,true);
    $part2 = array_slice($array,$position,null,true);
    $array = array_merge($part1,array($position=>$element),$part2);
    foreach($array as $key=>$item) {
      if (is_null($item)) {
        unset($array[$key]);
      }
    }
  }
  elseif (is_null($position)) {
    $array[] = $element;
  }  
  elseif (!isset($array[$position])) {
    $array[$position] = $element;
  }
  $array = array_merge($array);
  return $array;
}

кредиты идут: http://binarykitten.com/php/52-php-insert-element-and-shift.html

0

Подсказка для добавления элемента в начале массива:

$a = array('first', 'second');
$a[-1] = 'i am the new first element';

то

foreach($a as $aelem)
    echo $a . ' ';
//returns first, second, i am...

а

for ($i = -1; $i < count($a)-1; $i++)
     echo $a . ' ';
//returns i am as 1st element
  • 13
    Подсказка для добавления элемента в начале: array_unshift($a,'i am the new first element');
0
function insert(&$arr, $value, $index){       
    $lengh = count($arr);
    if($index<0||$index>$lengh)
        return;

    for($i=$lengh; $i>$index; $i--){
        $arr[$i] = $arr[$i-1];
    }

    $arr[$index] = $value;
}
0

Обычно со скалярными значениями:

$elements = array('foo', ...);
array_splice($array, $position, $length, $elements);

Чтобы вставить один элемент массива в ваш массив, не забудьте обернуть массив в массив (так как это было скалярное значение!):

$element = array('key1'=>'value1');
$elements = array($element);
array_splice($array, $position, $length, $elements);

иначе все ключи массива будут добавляться по частям.

-1

Для вставки элементов в массив со строковыми ключами вы можете сделать что-то вроде этого:

/* insert an element after given array key
 * $src = array()  array to work with
 * $ins = array() to insert in key=>array format
 * $pos = key that $ins will be inserted after
 */ 
function array_insert_string_keys($src,$ins,$pos) {

    $counter=1;
    foreach($src as $key=>$s){
        if($key==$pos){
            break;
        }
        $counter++;
    } 

    $array_head = array_slice($src,0,$counter);
    $array_tail = array_slice($src,$counter);

    $src = array_merge($array_head, $ins);
    $src = array_merge($src, $array_tail);

    return($src); 
} 
  • 2
    почему бы не $src = array_merge($array_head, $ins, $array_tail); ?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню