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.

Lua
fonte
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 ]
magro
fonte
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]

Maksym
fonte
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)

Abdennour TOUMI
fonte
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

zangw
fonte
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 ) 
dreftymac
fonte
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);

ozimax06
fonte
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.

AmerllicA
fonte
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]

Ben Adam
fonte
9

var testdata = new Array();
testdata = [23, 45, 12, 67];
testdata = [34, ...testdata]; 
console.log(testdata)

Tirkesh Turkesh
fonte
1
Esta é a mesma resposta que Abdennour TOUMI
T04435 27/02/19
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

Jenny O'Reilly
fonte
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' );
Srikrushna
fonte
É uma resposta correta. Obrigado Srikrushna
Khanh Tran