Estou procurando um método de inserção de matriz JavaScript, no estilo de:
arr.insert(index, item)
De preferência no jQuery, mas qualquer implementação em JavaScript funcionará neste momento.
Estou procurando um método de inserção de matriz JavaScript, no estilo de:
arr.insert(index, item)
De preferência no jQuery, mas qualquer implementação em JavaScript funcionará neste momento.
Respostas:
O que você deseja é a splice
função no objeto de matriz nativa.
arr.splice(index, 0, item);
irá inserir item
em arr
no índice especificado (excluindo 0
itens em primeiro lugar, que é, é apenas uma inserção).
Neste exemplo, criaremos uma matriz e adicionaremos um elemento a ela no índice 2:
var arr = [];
arr[0] = "Jani";
arr[1] = "Hege";
arr[2] = "Stale";
arr[3] = "Kai Jim";
arr[4] = "Borge";
console.log(arr.join());
arr.splice(2, 0, "Lene");
console.log(arr.join());
arr.splice(2,3)
removerá 3 elementos começando no índice 2. Sem passar o terceiro .... Nésimo parâmetro, nada é inserido. Portanto, o nome insert()
também não faz justiça.
Você pode implementar o Array.insert
método fazendo o seguinte:
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
Então você pode usá-lo como:
var arr = [ 'A', 'B', 'D', 'E' ];
arr.insert(2, 'C');
// => arr == [ 'A', 'B', 'C', 'D', 'E' ]
Array.prototype.insert = function (index, items) { this.splice.apply(this, [index, 0].concat(items)); }
Além da emenda, você pode usar essa abordagem que não altera a matriz original, mas cria uma nova matriz com o item adicionado. Você deve evitar a mutação sempre que possível. Estou usando o operador de propagação ES6 aqui.
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, newItem) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted item
newItem,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10)
console.log(result)
// [1, 10, 2, 3, 4, 5]
Isso pode ser usado para adicionar mais de um item, aprimorando um pouco a função para usar o operador restante para os novos itens e espalhá-lo no resultado retornado também
const items = [1, 2, 3, 4, 5]
const insert = (arr, index, ...newItems) => [
// part of the array before the specified index
...arr.slice(0, index),
// inserted items
...newItems,
// part of the array after the specified index
...arr.slice(index)
]
const result = insert(items, 1, 10, 20)
console.log(result)
// [1, 10, 20, 2, 3, 4, 5]
insert
Métodos de matriz personalizados/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
this.splice.apply(this, [index, 0].concat(
Array.prototype.slice.call(arguments, 1)));
return this;
};
Pode inserir vários elementos (como nativo splice
faz) e suporta encadeamento:
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(1, 6);
// ["b", "X", "Y", "Z", "c"]
/* Syntax:
array.insert(index, value1, value2, ..., valueN) */
Array.prototype.insert = function(index) {
index = Math.min(index, this.length);
arguments.length > 1
&& this.splice.apply(this, [index, 0].concat([].pop.call(arguments)))
&& this.insert.apply(this, arguments);
return this;
};
Ele pode mesclar matrizes dos argumentos com a matriz fornecida e também suporta encadeamento:
["a", "b", "c", "d"].insert(2, "V", ["W", "X", "Y"], "Z").join("-");
// "a-b-V-W-X-Y-Z-c-d"
["b", "X", "Y", "Z", "c"]
. Por que não está "d"
incluído? Parece-me que se você colocar 6 como o segundo parâmetro de slice()
e houver 6 elementos na matriz a partir do índice especificado, deverá obter todos os 6 elementos no valor de retorno. (O documento diz howMany
para esse parâmetro.) Developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/…
["a", "b", "c", "d"].insert(2, "X", "Y", "Z").slice(3, 3);
=>[ ]
slice
método e não splice
, ao qual você está se referindo no comentário. O segundo parâmetro de slice
(nomeado end
) é o índice baseado em zero no qual finalizar a extração. slice
extrai até, mas não incluiend
. Portanto, depois de insert
ter ["a", "b", "X", "Y", "Z", "c", "d"]
, a partir do qual slice
extrai elementos com índices de 1
até 6
, ou seja, de "b"
até, "d"
mas não incluindo "d"
. Isso faz sentido?
Se você deseja inserir vários elementos em uma matriz de uma só vez, confira esta resposta do Stack Overflow: Uma maneira melhor de unir uma matriz em uma matriz em javascript
Também aqui estão algumas funções para ilustrar os dois exemplos:
function insertAt(array, index) {
var arrayToInsert = Array.prototype.splice.apply(arguments, [2]);
return insertArrayAt(array, index, arrayToInsert);
}
function insertArrayAt(array, index, arrayToInsert) {
Array.prototype.splice.apply(array, [index, 0].concat(arrayToInsert));
return array;
}
Finalmente, aqui está um jsFiddle para que você possa ver por si mesmo: http://jsfiddle.net/luisperezphd/Wc8aS/
E é assim que você usa as funções:
// if you want to insert specific values whether constants or variables:
insertAt(arr, 1, "x", "y", "z");
// OR if you have an array:
var arrToInsert = ["x", "y", "z"];
insertArrayAt(arr, 1, arrToInsert);
Para programação funcional adequada e propósitos de encadeamento, uma invenção Array.prototype.insert()
é essencial. Na verdade, a emenda poderia ter sido perfeita se tivesse retornado a matriz mutada em vez de uma matriz vazia totalmente sem sentido. Então aqui vai
Array.prototype.insert = function(i,...rest){
this.splice(i,0,...rest)
return this
}
var a = [3,4,8,9];
document.write("<pre>" + JSON.stringify(a.insert(2,5,6,7)) + "</pre>");
Bem, o que foi dito acima Array.prototype.splice()
muda com a matriz original e alguns podem reclamar como "você não deve modificar o que não lhe pertence" e isso pode acabar se tornando correto também. Então, para o bem-estar público, gostaria de dar outro Array.prototype.insert()
que não modifique a matriz original. Aqui vai;
Array.prototype.insert = function(i,...rest){
return this.slice(0,i).concat(rest,this.slice(i));
}
var a = [3,4,8,9],
b = a.insert(2,5,6,7);
console.log(JSON.stringify(a));
console.log(JSON.stringify(b));
splice
modifica a matriz original, não acho que a "programação funcional apropriada" pertença a nenhum lugar nas proximidades splice
.
Eu recomendo usar JavaScript puro neste caso, também não há método de inserção em JavaScript, mas temos um método que é um método Array interno que faz o trabalho para você, chamado de emenda ...
Vamos ver o que é splice () ...
O método splice () altera o conteúdo de uma matriz removendo os elementos existentes e / ou adicionando novos elementos.
OK, imagine que temos esta matriz abaixo:
const arr = [1, 2, 3, 4, 5];
Podemos remover 3
assim:
arr.splice(arr.indexOf(3), 1);
Ele retornará 3, mas se verificarmos o arr agora, temos:
[1, 2, 4, 5]
Até agora, tudo bem, mas como podemos adicionar um novo elemento à matriz usando emenda? Vamos colocar de volta 3 no arr ...
arr.splice(2, 0, 3);
Vamos ver o que fizemos ...
Usamos emenda novamente, mas desta vez para o segundo argumento, passamos 0 , significa que não queremos excluir nenhum item, mas, ao mesmo tempo, adicionamos o terceiro argumento, que é 3, que será adicionado no segundo índice ...
Você deve estar ciente de que podemos excluir e adicionar ao mesmo tempo, por exemplo, agora podemos fazer:
arr.splice(2, 2, 3);
O que excluirá 2 itens no índice 2, depois adicionará 3 no índice 2 e o resultado será:
[1, 2, 3, 5];
Isso está mostrando como cada item da emenda funciona:
array.splice (start, deleteCount, item1, item2, item3 ...)
Anexar elemento único a um índice específico
//Append at specific position(here at index 1)
arrName.splice(1, 0,'newName1');
//1: index number, 0: number of element to remove, newName1: new element
//Append at specific position (here at index 3)
arrName[3] = 'newName1';
Anexar vários elementos em um índice específico
//Append from index number 1
arrName.splice(1, 0,'newElemenet1', 'newElemenet2', 'newElemenet3');
//1: index number from where append start,
//0: number of element to remove,
//newElemenet1,2,3: new elements
arrName[3] = 'newName1';
será acrescentado se a matriz tiver apenas 3 elementos. Se houver um elemento no índice 3, este será substituído. Se você quiser acrescentar no final, é melhor usararrName.push('newName1');
Outra solução possível, com o uso de Array#reduce
.
var arr = ["apple", "orange", "raspberry"],
arr2 = [1, 2, 4];
function insert(arr, item, index) {
arr = arr.reduce(function(s, a, i) {
i == index ? s.push(item, a) : s.push(a);
return s;
}, []);
console.log(arr);
}
insert(arr, "banana", 1);
insert(arr2, 3, 2);
Aqui estão duas maneiras:
const array = [ 'My', 'name', 'Hamza' ];
array.splice(2, 0, 'is');
console.log("Method 1 : ", array.join(" "));
OU
Array.prototype.insert = function ( index, item ) {
this.splice( index, 0, item );
};
const array = [ 'My', 'name', 'Hamza' ];
array.insert(2, 'is');
console.log("Method 2 : ", array.join(" "));
Mesmo que isso já tenha sido respondido, estou adicionando esta nota para uma abordagem alternativa.
Eu queria colocar um número conhecido de itens em uma matriz, em posições específicas, pois elas saem de uma "matriz associativa" (isto é, um objeto) que, por definição, não é garantido que esteja em uma ordem classificada. Eu queria que a matriz resultante fosse uma matriz de objetos, mas os objetos estivessem em uma ordem específica na matriz, já que uma matriz garante sua ordem. Então eu fiz isso.
Primeiro, o objeto de origem, uma string JSONB recuperada do PostgreSQL. Eu queria que ele fosse classificado pela propriedade "order" em cada objeto filho.
var jsonb_str = '{"one": {"abbr": "", "order": 3}, "two": {"abbr": "", "order": 4}, "three": {"abbr": "", "order": 5}, "initialize": {"abbr": "init", "order": 1}, "start": {"abbr": "", "order": 2}}';
var jsonb_obj = JSON.parse(jsonb_str);
Como o número de nós no objeto é conhecido, primeiro crio uma matriz com o comprimento especificado:
var obj_length = Object.keys(jsonb_obj).length;
var sorted_array = new Array(obj_length);
E, em seguida, itere o objeto, colocando os objetos temporários recém-criados nos locais desejados na matriz, sem que ocorra realmente uma "classificação".
for (var key of Object.keys(jsonb_obj)) {
var tobj = {};
tobj[key] = jsonb_obj[key].abbr;
var position = jsonb_obj[key].order - 1;
sorted_array[position] = tobj;
}
console.dir(sorted_array);
Qualquer um que ainda esteja tendo problemas com esse problema, tentou todas as opções acima e nunca conseguiu. Estou compartilhando minha solução, isso é para levar em consideração que você não deseja declarar explicitamente as propriedades do seu objeto versus a matriz.
function isIdentical(left, right){
return JSON.stringify(left) === JSON.stringify(right);
}
function contains(array, obj){
let count = 0;
array.map((cur) => {
if(this.isIdentical(cur, obj)) count++;
});
return count > 0;
}
Essa é uma combinação de iterar a matriz de referência e compará-la com o objeto que você deseja verificar, converter os dois em uma sequência e iterar se corresponder. Então você pode apenas contar. Isso pode ser melhorado, mas é aqui que eu me acomodo. Espero que isto ajude.
Tendo lucro do método de redução da seguinte forma:
function insert(arr, val, index) {
return index >= arr.length
? arr.concat(val)
: arr.reduce((prev, x, i) => prev.concat(i === index ? [val, x] : x), []);
}
Dessa forma, podemos retornar uma nova matriz (será uma maneira funcional legal - muito melhor do que usar push ou emenda) com o elemento inserido no índice e, se o índice for maior que o comprimento da matriz, ele será inserido no fim.
Array#splice()
é o caminho a seguir, a menos que você realmente queira evitar a mutação da matriz. Dado 2 matrizes arr1
e arr2
, aqui está como você iria inserir o conteúdo de arr2
dentro arr1
após o primeiro elemento:
const arr1 = ['a', 'd', 'e'];
const arr2 = ['b', 'c'];
arr1.splice(1, 0, ...arr2); // arr1 now contains ['a', 'b', 'c', 'd', 'e']
console.log(arr1)
Se você estiver preocupado em alterar a matriz (por exemplo, se estiver usando o Immutable.js), poderá usar slice()
, para não confundir splice()
com a 'p'
.
const arr3 = [...arr1.slice(0, 1), ...arr2, ...arr1.slice(1)];
Eu tentei isso e está funcionando bem!
var initialArr = ["India","China","Japan","USA"];
initialArr.splice(index, 0, item);
Índice é a posição em que você deseja inserir ou excluir o elemento. 0 ou seja, o segundo parâmetro define o número de elemento do índice a ser removido. As novas entradas que você deseja criar na matriz. Pode ser um ou mais de um.
initialArr.splice(2, 0, "Nigeria");
initialArr.splice(2, 0, "Australia","UK");
Aqui está uma função que eu uso em um dos meus aplicativos.
Isso verifica se o item sai
let ifExist = (item, strings = [ '' ], position = 0) => {
// output into an array with empty string. Important just in case their is no item.
let output = [ '' ];
// check to see if the item that will be positioned exist.
if (item) {
// output should equal to array of strings.
output = strings;
// use splice in order to break the array.
// use positition param to state where to put the item
// and 0 is to not replace an index. Item is the actual item we are placing at the prescribed position.
output.splice(position, 0, item);
}
//empty string is so we do not concatenate with comma or anything else.
return output.join("");
};
E então eu chamo isso abaixo.
ifExist("friends", [ ' ( ', ' )' ], 1)} // output: ( friends )
ifExist("friends", [ ' - '], 1)} // output: - friends
ifExist("friends", [ ':'], 0)} // output: friends:
Um pouco mais antigo, mas tenho que concordar com o Redu acima porque o splice definitivamente tem uma interface um pouco confusa. E a resposta dada por cdbajorin de que "ele retorna apenas uma matriz vazia quando o segundo parâmetro é 0. Se for maior que 0, retorna os itens removidos da matriz" está, enquanto preciso, provando o ponto. A intenção da função é unir ou, como já foi dito por Jakob Keller, "unir-se ou conectar-se, também para alterar. Você tem uma matriz estabelecida que agora está mudando, o que envolveria adicionar ou remover elementos ...". o valor de retorno dos elementos, se houver, que foram removidos é, na melhor das hipóteses, estranho. E eu 100% concorda que esse método poderia ser mais adequado ao encadeamento se tivesse retornado o que parece natural, uma nova matriz com os elementos emendados adicionados. Depois, você pode fazer coisas como ["19", "17"]. Splice (1,0, "18"). Join ("...") ou o que quiser com a matriz retornada. O fato de que ele retorna o que foi removido é meio que IMHO sem sentido. Se a intenção do método era "cortar um conjunto de elementos" e essa era a única intenção, talvez. Parece que, se eu ainda não sei o que estou cortando, provavelmente tenho poucas razões para cortar esses elementos, não é? Seria melhor se ele se comportasse como concat, mapear, reduzir, cortar, etc., onde uma nova matriz é feita a partir da matriz existente, em vez de mudar a matriz existente. Tudo isso é encadeado e isso é um problema significativo. É bastante comum a manipulação de array em cadeia. Parece que o idioma precisa seguir uma direção ou outra e tentar cumpri-lo o máximo possível. Javascript sendo funcional e menos declarativo, parece apenas um desvio estranho da norma.
Hoje (2020.04.24) realizo testes para soluções escolhidas para matrizes grandes e pequenas. Testei-os no MacOs High Sierra 10.13.6 no Chrome 81.0, Safari 13.1, Firefox 75.0.
Para todos os navegadores
slice
ereduce
(D, E, F) são geralmente 10x-100x mais rápido do que as soluções em-lugarsplice
(AI, BI, CI) foram as mais rápidas (às vezes ~ 100x - mas isso depende do tamanho da matriz)Os testes foram divididos em dois grupos: soluções no local (AI, BI, CI) e soluções não no local (D, E, F) e foram realizados em dois casos
O código testado é apresentado no snippet abaixo
Os resultados de exemplo para matriz pequena no chrome estão abaixo