Inserir novo item na matriz em qualquer posição no PHP

Respostas:

920

Você pode achar isso um pouco mais intuitivo. Requer apenas uma chamada de função para array_splice:

$original = array( 'a', 'b', 'c', 'd', 'e' );
$inserted = array( 'x' ); // not necessarily an array, see manual quote

array_splice( $original, 3, 0, $inserted ); // splice in at position 3
// $original is now a b c x d e

Se a substituição for apenas um elemento, não é necessário colocar array () em torno dele, a menos que o elemento seja uma matriz em si, um objeto ou NULL.

jay.lee
fonte
32
É estranho que uma funcionalidade tão básica esteja realmente oculta, pois o principal objetivo dessa função, conforme descrito na documentação, é algo diferente (substituir itens nas matrizes). Sim, é indicado na seção de argumentos, mas se você estiver apenas digitalizando as descrições das funções para descobrir o que usar para inserir nas matrizes, nunca a encontrará.
Mahn
23
Apenas dizendo que isso não preservará as chaves na $insertedmatriz.
27512 mauris
6
Também em PHP manual, o exemplo # 1: php.net/manual/en/function.array-splice.php
marcovtwout
3
@JacerOmri está totalmente certo, ambas as declarações são válidas. Você pode transmitir um valor de qualquer tipo, mas ele pode não se comportar da mesma maneira para uma matriz, objeto ou nulo. Para escalares, a conversão de tipo (array)$scalaré equivalente a array($scalar), mas para uma matriz, um objeto ou nulo, ela será ignorada (matriz), convertida em uma matriz (objeto) ou se tornará uma matriz vazia (nula) - consulte php.net / manual / pt /…
Lukas
2
@ SunilPachlangia, adelval e outros: com matrizes multidimensionais, você precisa agrupar a substituição em uma matriz, está documentada. Eu ainda trouxe a nota aqui para que as pessoas parem de cometer o erro.
Félix Gagnon-Grenier
47

Uma função que pode ser inserida nas posições inteiro e string:

/**
 * @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)
        );
    }
}

Uso inteiro:

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

Uso da corda:

$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',
  ),
)
Halil Özgür
fonte
1
O array_splice()perde as chaves, enquanto array_merge()que não. Assim, os resultados da primeira função pode ser muito surpreendente ... Especialmente porque se você tem dois elementos com a mesma chave, apenas o valor do último é mantido ...
Alexis Wilke
33
$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)
Âmbar
fonte
10
Usando +vez de array_mergepode preservar chaves
mauris
1
Agora eu posso adicionar mais elementos antes de um índice
Abbas
5

Dessa forma, você pode inserir matrizes:

function array_insert(&$array, $value, $index)
{
    return $array = array_merge(array_splice($array, max(0, $index - 1)), array($value), $array);
}
Aleksandr Makov
fonte
2
Essa função não salva o pedido na matriz.
Daniel Petrovaliev
5

Não há nenhuma função nativa do PHP (que eu saiba) que possa fazer exatamente o que você solicitou.

Eu escrevi 2 métodos que eu acredito que são adequados para o propósito:

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

Embora seja mais rápido e provavelmente mais eficiente em termos de memória, isso só é realmente adequado quando não é necessário manter as chaves da matriz.

Se você precisar manter as chaves, o seguinte seria mais adequado;

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;
}
Um garoto chamado Su
fonte
1
Isso funciona bem. No entanto, no segundo exemplo, em sua função insertBefore(), você deve retornar em $tmpArrayvez de $input.
Christoph Fischer
4

Com base na ótima resposta do @Halil, aqui está a função simples de como inserir um novo elemento após uma chave específica, preservando as teclas inteiras:

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)
    );
} 
d.raev
fonte
4

Se você deseja manter as chaves da matriz inicial e também adicionar uma matriz com chaves, use a função abaixo:

function insertArrayAtPosition( $array, $insert, $position ) {
    /*
    $array : The initial array i want to modify
    $insert : the new array i want to add, eg array('key' => 'value') or array('value')
    $position : the position where the new array will be inserted into. Please mind that arrays start at 0
    */
    return array_slice($array, 0, $position, TRUE) + $insert + array_slice($array, $position, NULL, TRUE);
}

Exemplo de chamada:

$array = insertArrayAtPosition($array, array('key' => 'Value'), 3);
Mayra M
fonte
3
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;
}
Henry Wong
fonte
3

Isto é o que funcionou para mim na matriz associativa:

/*
 * Inserts a new key/value after the key in the array.
 *
 * @param $key
 *   The key to insert after.
 * @param $array
 *   An array to insert in to.
 * @param $new_key
 *   The key to insert.
 * @param $new_value
 *   An value to insert.
 *
 * @return
 *   The new array if the key exists, FALSE otherwise.
 *
 * @see array_insert_before()
 */
function array_insert_after($key, array &$array, $new_key, $new_value) {
  if (array_key_exists($key, $array)) {
    $new = array();
    foreach ($array as $k => $value) {
      $new[$k] = $value;
      if ($k === $key) {
        $new[$new_key] = $new_value;
      }
    }
    return $new;
  }
  return FALSE;
}

A fonte da função - esta postagem no blog . Também há uma função útil para inserir ANTES da chave específica.

Oksana Romaniv
fonte
2

Esta também é uma solução funcional:

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

créditos vão para: http://binarykitten.com/php/52-php-insert-element-and-shift.html

Mike Doh
fonte
2

Solução por jay.lee é perfeita. Caso você queira adicionar itens a uma matriz multidimensional, primeiro adicione uma matriz dimensional única e, em seguida, substitua-a depois.

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

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

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

Adicionar um item no mesmo formato a essa matriz adicionará todos os novos índices de matriz como itens, em vez de apenas item.

$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

Nota: A adição de itens diretamente a uma matriz multidimensional com array_splice adicionará todos os seus índices como itens, em vez de apenas esse item.

Abdul Mannan
fonte
2

Você pode usar isso

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

Normalmente, com valores escalares:

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

Para inserir um único elemento de matriz em sua matriz, não se esqueça de agrupar a matriz em uma matriz (pois era um valor escalar!):

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

caso contrário, todas as teclas da matriz serão adicionadas peça por peça.

marca
fonte
1

Dica para adicionar um elemento no início de uma matriz :

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

então:

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

mas:

for ($i = -1; $i < count($a)-1; $i++)
     echo $a . ' ';
//returns i am as 1st element
forsberg
fonte
13
Dica para adicionar um elemento no início:array_unshift($a,'i am the new first element');
1

se não tiver certeza, NÃO UTILIZE ESTES :

$arr1 = $arr1 + $arr2;

OU

$arr1 += $arr2;

porque com + matriz original será substituído. ( ver fonte )

T.Todua
fonte
1

Tente este:

$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;
}
Máx.
fonte
1
function array_insert($array, $position, $insert) {
    if ($position > 0) {
        if ($position == 1) {
            array_unshift($array, array());
        } else {
            $position = $position - 1;
            array_splice($array, $position, 0, array(
                ''
            ));
        }
        $array[$position] = $insert;
    }

    return $array;
}

Exemplo de chamada:

$array = array_insert($array, 1, ['123', 'abc']);
xayer
fonte
0

Para inserir elementos em uma matriz com chaves de string, você pode fazer algo assim:

/* 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); 
} 
Bryan Emplastros
fonte
2
por que não $src = array_merge($array_head, $ins, $array_tail);?
cartbeforehorse