Como posso adicionar novos elementos de matriz no início de uma matriz em Javascript?


1586

Eu preciso adicionar ou adicionar elementos no início de uma matriz.

Por exemplo, se minha matriz se parecer com abaixo:

[23, 45, 12, 67]

E a resposta da minha chamada AJAX é que 34eu quero que a matriz atualizada seja a seguinte:

[34, 23, 45, 12, 67]

Atualmente, estou planejando fazer assim:

var newArray = [];
newArray.push(response);

for (var i = 0; i < theArray.length; i++) {
    newArray.push(theArray[i]);
}

theArray = newArray;
delete newArray;

Existe alguma maneira melhor de fazer isso? O Javascript tem alguma funcionalidade interna que faz isso?

A complexidade do meu método é O(n)e seria realmente interessante ver melhores implementações.


9
FYI: Se você precisar inserir continuamente um elemento no início de uma matriz, é mais rápido usar pushinstruções seguidas por uma chamada para reverse, em vez de chamar unshifto tempo todo.
Jenny O'Reilly

2
@ JennyO'Reilly, você deve postar isso como resposta. Correspondeu perfeitamente ao meu caso de uso. obrigado #
7742

2
Testes de desempenho: jsperf.com/adding-element-to-the-array-start Mas os resultados são diferentes para cada navegador.
Avernikoz

Respostas:


2813

Use unshift. É como push, exceto que ele adiciona elementos ao início da matriz em vez do final.

  • unshift/ push- adiciona um elemento ao início / fim de uma matriz
  • shift/ pop - remove e retorna o primeiro / último elemento de uma matriz

Um diagrama simples ...

   unshift -> array <- push
   shift   <- array -> pop

e gráfico:

          add  remove  start  end
   push    X                   X
    pop           X            X
unshift    X             X
  shift           X      X

Confira a documentação da matriz MDN . Praticamente todas as linguagens que têm a capacidade de empurrar / pop elementos de uma matriz também têm a capacidade de desviar / mudar (às vezes chamado push_front/ pop_front) elementos, você nunca precisará implementá-los.


Conforme apontado nos comentários, se você deseja evitar a mutação de sua matriz original, pode usar concat, que concatena duas ou mais matrizes juntas. Você pode usar isso para empurrar funcionalmente um único elemento para a frente ou para trás de uma matriz existente; para fazer isso, você precisa transformar o novo elemento em uma única matriz de elementos:

const array = [ 3, 2, 1 ]

const newFirstElement = 4

const newArray = [newFirstElement].concat(array) // [ 4, 3, 2, 1 ]

concattambém pode acrescentar itens. Os argumentos para concatpodem ser de qualquer tipo; eles estão implicitamente agrupados em uma matriz de elemento único, se ainda não forem uma matriz:

const array = [ 3, 2, 1 ]

const newLastElement  = 0

// Both of these lines are equivalent:
const newArray1 = array.concat(newLastElement)   // [ 3, 2, 1, 0 ]
const newArray2 = array.concat([newLastElement]) // [ 3, 2, 1, 0 ]

51
O uso concatpode ser preferível, pois retorna a nova matriz. Muito útil para encadeamento. [thingToInsertToFront].concat(originalArray).reduce(fn).reverse().map(fn)etc ... Se você usa unshift, não pode fazer esse encadeamento porque tudo o que você recebe é o comprimento.
StJohn3D

4
shift / unshift, push / pop, emenda. Nomes muito lógicos para esses métodos.
Linuxunil

1398

imagem de operações de matriz

var a = [23, 45, 12, 67];
a.unshift(34);
console.log(a); // [34, 23, 45, 12, 67]


117
A razão pela qual as pessoas precisam de uma orientação visual para 4 funções diárias usadas é por causa dos nomes de funções criptografadas ... Por que o unshift não é chamado de Inserção? A mudança deve ser Remover. etc ...
Pascal

76
// Por que unshift não é chamado de Inserção? // Ele vem das convenções da linguagem de programação C em que os elementos da matriz foram tratados como uma pilha. (veja perlmonks.org/?node_id=613129 para uma explicação completa)
dreftymac

25
@ Pascal Não, inserir e remover seria um nome particularmente ruim para isso; eles implicam acesso aleatório, em vez de adicionar / remover da frente da matriz
meagar

25
Eu teria pensado que unshift deve remover a primeira chave, e mudança iria inserir na primeira chave, mas isso é apenas o meu pensamento geral
Shannon Hochkins

27
Eu gosto da referência DNA
Hunter WebDev

235

Com o ES6, use o operador spread ...:

DEMO

var arr = [23, 45, 12, 67];
arr = [34, ...arr]; // RESULT : [34,23, 45, 12, 67]

console.log(arr)


19
também cria uma nova matriz, útil para funções puras
devonj

qual é a implicação de desempenho aqui? É mais lento do que usar unshift ()?
Peter T.

1
Claro, será mais lento, pois é uma matriz imutável (criando uma nova matriz). Se você estiver trabalhando com uma grande variedade ou se o desempenho for seu primeiro requisito, considere usá-lo concat.
Abdennour TOUMI

desempenho não é importante em 2018, uma nova versão no navegador e nó de obter o mesmo desempenho
stackdave

75

Outra maneira de fazer isso através concat

var arr = [1, 2, 3, 4, 5, 6, 7];
console.log([0].concat(arr));

A diferença entre concate unshifté que concatretorna uma nova matriz. O desempenho entre eles pode ser encontrado aqui .

function fn_unshift() {
  arr.unshift(0);
  return arr;
}

function fn_concat_init() {
  return [0].concat(arr)
}

Aqui está o resultado do teste

insira a descrição da imagem aqui


Seria bom que sua resposta anexasse a comparação de desempenho de ambos, além de adicionar a referência.
Ivan De Paz Centeno

Acabei de descobrir que o jsPerf está temporariamente indisponível enquanto estamos trabalhando no lançamento da v2. Por favor, tente novamente mais tarde a partir do link. Outro bom motivo para incluir os resultados em vez de vincular a eles.
Tigger

jsPref resultado: unshift: 25510 ± 3,18% a 99% mais lento concat: 2436894 ± 3,39% mais rápido
Iluminador

No último Safari, o fn_unshift () roda mais rápido.
passatgt

No Safari mais recente (v 10), fn_unshift () é mais lento novamente.
Rmcsharry 9/11

45

Folha de dicas rápida:

Os termos shift / unshift e push / pop podem ser um pouco confusos, pelo menos para as pessoas que podem não estar familiarizadas com a programação em C.

Se você não conhece o jargão, aqui está uma tradução rápida de termos alternativos, que podem ser mais fáceis de lembrar:

* array_unshift()  -  (aka Prepend ;; InsertBefore ;; InsertAtBegin )     
* array_shift()    -  (aka UnPrepend ;; RemoveBefore  ;; RemoveFromBegin )

* array_push()     -  (aka Append ;; InsertAfter   ;; InsertAtEnd )     
* array_pop()      -  (aka UnAppend ;; RemoveAfter   ;; RemoveFromEnd ) 

20

você tem uma matriz: var arr = [23, 45, 12, 67];

Para adicionar um item ao começo, você deseja usar splice:

var arr = [23, 45, 12, 67];
arr.splice(0, 0, 34)
console.log(arr);


arr.splice (0, comprimento arr., 34);
Lior Elrom

1
@LiorElrom, o que o seu snippet faz?
Janus Troelsen

@poushy que é específico do navegador, no Firefox 54 é unshift50% mais rápido (mas principalmente mais legível)
icl7126

@poushy Não é mais. Muito mais devagar.
Andrew Andrew

17

Sem mutação

Na verdade, todos unshift/ pushe shift/ pop modificam a matriz de origem.

O unshift/ pushadiciona um item à matriz existente a partir do início / fim e shift/ popremove um item do início / fim de uma matriz.

Mas existem poucas maneiras de adicionar itens a uma matriz sem uma mutação. o resultado é uma nova matriz, para adicionar ao final da matriz, use o código abaixo:

const originArray = ['one', 'two', 'three'];
const newItem = 4;

const newArray = originArray.concat(newItem); // ES5
const newArray2 = [...originArray, newItem]; // ES6+

Para adicionar ao início da matriz original, use o código abaixo:

const originArray = ['one', 'two', 'three'];
const newItem = 0;

const newArray = (originArray.slice().reverse().concat(newItem)).reverse(); // ES5
const newArray2 = [newItem, ...originArray]; // ES6+

Com a maneira acima, você adiciona ao início / fim de uma matriz sem uma mutação.


Acabei de colocar uma slicefunção no final de originArraypara impedi-la de mutabilidade.
Ahmad Khani

1
Impressionante! Quando se trata de gerenciamento de estado (Redux) ... essa resposta é preciosa!
Pedro Ferreira

1
Esta é a maneira correta!
mmm

10

Usando a desestruturação do ES6: (evitando a mutação da matriz original)

const newArr = [item, ...oldArr]



8

Se você precisar inserir continuamente um elemento no início de uma matriz, é mais rápido usar pushinstruções seguidas por uma chamada para reverse, em vez de chamar unshifto tempo todo.

Teste de benchmark: http://jsben.ch/kLIYf


1
Nota: a matriz inicial deve estar vazia.
192kb 15/08/19

5

Usando splicenós inserimos um elemento em uma matriz no início:

arrName.splice( 0, 0, 'newName1' );

É uma resposta correta. Obrigado Srikrushna
Khanh Tran
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.