Eu tenho duas matrizes. O primeiro array contém alguns valores, enquanto o segundo array contém índices dos valores que devem ser removidos do primeiro array. Por exemplo:
var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
Quero remover os valores presentes nos índices 0,2,4
de valuesArr
. Achei que o splice
método nativo pudesse ajudar, então pensei em:
$.each(removeValFromIndex,function(index,value){
valuesArr.splice(value,1);
});
Mas não funcionou porque depois de cada um splice
, os índices dos valores em valuesArr
eram diferentes. Eu poderia resolver esse problema usando um array temporário e copiando todos os valores para o segundo array, mas gostaria de saber se há algum método nativo para o qual possamos passar vários índices para remover valores de um array.
Eu preferiria uma solução jQuery. (Não tenho certeza se posso usar grep
aqui)
fonte
$.each(rvm.reverse(), function(e, i ) {})
removeValFromIndex
estiver classificado em ordem crescenteAqui está um que eu uso quando não vou com lodash / sublinhado:
fonte
slice
teria que recalcular os índices a serem removidos (-1 emIndexestoBeRemoved
), mas realmente funciona!IndexesToBeRemoved
array for classificado em ordem crescente.IndexesToBeRemoved
for classificado (crescente).Não
in-place
, mas pode ser feito usandogrep
einArray
funções dejQuery
.verifique este violino.
fonte
valuesArr = $.grep(...);
Eu sugiro que você use Array.prototype.filter
fonte
A referência MDN está aqui
fonte
Em JS puro, você pode percorrer a matriz de trás para frente, portanto
splice()
, não bagunçará os índices dos elementos a seguir no loop:fonte
Parece necessário postar uma resposta com o
O(n)
tempo :). O problema com a solução de emenda é que, devido à implementação subjacente do array ser literalmente um array , cadasplice
chamada levaráO(n)
algum tempo. Isso é mais evidente quando configuramos um exemplo para explorar este comportamento:Isso remove elementos do meio para o início, portanto, cada remoção força o mecanismo js a copiar os
n/2
elementos, temos(n/2)^2
operações de cópia no total, que são quadráticas.A solução de emenda (assumindo que
is
já está classificada em ordem decrescente para se livrar dos overheads) é assim:No entanto, não é difícil implementar uma solução de tempo linear, reconstruindo o array do zero, usando uma máscara para ver se copiamos os elementos ou não (sort irá empurrar para
O(n)log(n)
). O seguinte é tal implementação (não quemask
seja booleano invertido para velocidade):Eu executei isso em jsperf.com e até mesmo
n=100
o método de emenda é 90% mais lento. Para maioresn
essa diferença será muito maior.fonte
Quick ES6 one liner:
fonte
removeValFromIndex
umSet()
e usar emremoveValFromIndex.has
vez deincludes
.Uma solução simples e eficiente (complexidade linear) usando filtro e Conjunto :
A grande vantagem dessa implementação é que a operação Set lookup (
has
função) leva um tempo constante, sendo mais rápida do que a resposta de Nevace, por exemplo.fonte
Isso funciona bem para mim e também ao excluir de uma série de objetos:
Pode haver uma maneira mais curta e mais eficiente de escrever isso, mas funciona.
fonte
Uma solução simples usando ES5. Isso parece mais apropriado para a maioria dos aplicativos hoje em dia, já que muitos não querem mais depender do jQuery etc.
Quando os índices a serem removidos são classificados em ordem crescente:
Quando os índices a serem removidos não são classificados:
fonte
Você pode corrigir seu código substituindo
removeValFromIndex
porremoveValFromIndex.reverse()
. Se não for garantido que essa matriz use a ordem crescente, você pode usarremoveValFromIndex.sort(function(a, b) { return b - a })
.fonte
removeValFromIndex
estiverem em ordem crescente.Aqui está uma possibilidade:
Exemplo em jsFiddle
MDN em Array.prototype.reduceRight
fonte
Se você estiver usando o underscore.js , você pode usar
_.filter()
para resolver o seu problema.Além disso, se você estiver tentando remover itens usando uma lista de itens em vez de índices, você pode simplesmente usar
_.without()
, assim:Agora
filteredArr
deveria ser["V2", "V4", "V5"]
fonte
filtro + indexOf (IE9 +):
Ou com filtro ES6 + encontrar (Edge +):
fonte
Aqui está uma rapidinha.
fonte
Parece que o Apply pode ser o que você está procurando.
talvez algo assim funcionasse?
fonte
.splice()
método não espera uma lista de elementos para remover, ele espera um único índice do elemento no qual iniciar a remoção, seguido pelo número de elementos a serem removidos ...Para vários itens ou item único:
Eu sugiro que você use Array.prototype.filter
Nunca use indexOf se você já conhece o índice !:
Faz:
com Hashes ... usando Array.prototype.map
fonte
Isso funciona. No entanto, você faria uma nova matriz no processo. Não tenho certeza se isso você deseja ou não, mas tecnicamente seria uma matriz contendo apenas os valores que você deseja.
fonte
Você pode tentar e usar
delete array[index]
Isso não removerá completamente o elemento, mas definirá o valor comoundefined
.fonte
Você pode construir um a
Set
partir do array e então criar um array a partir do conjunto.fonte