programing

Javascript / jQuery의 배열에서 여러 요소 제거

nasanasas 2020. 8. 29. 11:11
반응형

Javascript / jQuery의 배열에서 여러 요소 제거


두 개의 배열이 있습니다. 첫 번째 배열에는 일부 값이 포함되고 두 번째 배열에는 첫 번째 배열에서 제거되어야하는 값의 인덱스가 포함됩니다. 예를 들면 :

var valuesArr = new Array("v1","v2","v3","v4","v5");   
var removeValFromIndex = new Array(0,2,4);

나는 인덱스에 값 선물을 제거 할 0,2,4에서 valuesArr. 기본 splice방법이 도움이 될 것이라고 생각하여 다음과 같이 생각해 냈습니다.

$.each(removeValFromIndex,function(index,value){
    valuesArr.splice(value,1);
});

그러나 각마다 splice값의 인덱스 valuesArr가 다르기 때문에 작동하지 않았습니다 . 임시 배열을 사용하고 모든 값을 두 번째 배열에 복사하여이 문제를 해결할 수 있지만 배열에서 값을 제거 할 여러 인덱스를 전달할 수있는 네이티브 메서드가 있는지 궁금합니다.

jQuery 솔루션을 선호합니다. ( grep여기에서 사용할 수 있는지 확실하지 않음 )


항상 평범한 오래된 for루프가 있습니다.

var valuesArr = ["v1","v2","v3","v4","v5"],
    removeValFromIndex = [0,2,4];    

for (var i = removeValFromIndex.length -1; i >= 0; i--)
   valuesArr.splice(removeValFromIndex[i],1);

를 통해 이동 removeValFromIndex역순으로하고 있습니다 .splice()아직 - 투 - 제거 할 항목의 인덱스를 엉망으로하지 않고.

위의 내용에서 대괄호가있는 array-literal 구문을 사용하여 두 배열을 선언했습니다. new Array()전달하는 매개 변수 수에 따라 다르게 응답 하므로 사용이 잠재적으로 혼란 스럽기 때문에 권장되는 구문 입니다.

편집 : 특정 순서가 아닌 인덱스 배열에 대한 다른 답변에 대한 귀하의 의견을 보았습니다. 이 경우 시작하기 전에 내림차순으로 정렬하십시오.

removeValFromIndex.sort(function(a,b){ return b - a; });

그리고 $.each()당신이 좋아 하는 루핑 / / 등 방법으로 그것을 따르십시오 .


다음은 lodash / underscore를 사용하지 않을 때 사용하는 것입니다.

while(IndexesToBeRemoved.length) {
    elements.splice(IndexesToBeRemoved.pop(), 1);
}

아닙니다 .의 기능을 in-place사용하여 수행 할 수 있습니다 .grepinArrayjQuery

var arr = $.grep(valuesArr, function(n, i) {
    return $.inArray(i, removeValFromIndex) ==-1;
});

alert(arr);//arr contains V2, V4

바이올린을 확인 하십시오 .


Array.prototype.filter 를 사용하는 것이 좋습니다.

var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];
valuesArr = valuesArr.filter(function(value, index) {
     return removeValFrom.indexOf(index) == -1;
})

function filtermethod(element, index, array) {  
    return removeValFromIndex.find(index)
}  
var result = valuesArr.filter(filtermethod);

MDN 참조는 여기


순수 JS에서는 배열을 거꾸로 반복 할 수 있으므로 루프에서 splice()다음 요소의 인덱스를 엉망으로 만들지 않습니다.

for (var i = arr.length - 1; i >= 0; i--) {
    if ( yuck(arr[i]) ) {
        arr.splice(i, 1);
    }
}

O(n)시간 과 함께 답변을 게시 할 필요가 있다고 느낍니다 :). 스플 라이스 솔루션의 문제점은 배열의 기본 구현이 문자 그대로 배열이기 때문에 각 splice호출에 O(n)시간 이 걸린다는 것 입니다. 이 동작을 악용하는 예제를 설정할 때 가장 두드러집니다.

var n = 100
var xs = []
for(var i=0; i<n;i++)
  xs.push(i)
var is = []
for(var i=n/2-1; i>=0;i--)
  is.push(i)

This removes elements starting from the middle to the start, hence each remove forces the js engine to copy n/2 elements, we have (n/2)^2 copy operations in total which is quadratic.

The splice solution (assuming is is already sorted in decreasing order to get rid of overheads) goes like this:

for(var i=0; i<is.length; i++)
  xs.splice(is[i], 1)

However, it is not hard to implement a linear time solution, by re-constructing the array from scratch, using a mask to see if we copy elements or not (sort will push this to O(n)log(n)). The following is such an implementation (not that mask is boolean inverted for speed):

var mask = new Array(xs.length)
for(var i=is.length - 1; i>=0; i--)
  mask[is[i]] = true
var offset = 0
for(var i=0; i<xs.length; i++){
  if(mask[i] === undefined){
    xs[offset] = xs[i]
    offset++
  }
}
xs.length = offset

I ran this on jsperf.com and for even n=100 the splice method is a full 90% slower. For larger n this difference will be much greater.


A simple solution using ES5. This seems more appropriate for most applications nowadays, since many do no longer want to rely on jQuery etc.

When the indexes to be removed are sorted in ascending order:

var valuesArr = ["v1", "v2", "v3", "v4", "v5"];   
var removeValFromIndex = [0, 2, 4]; // ascending

removeValFromIndex.reverse().forEach(function(index) {
  valuesArr.splice(index, 1);
});

When the indexes to be removed are not sorted:

var valuesArr = ["v1", "v2", "v3", "v4", "v5"];   
var removeValFromIndex = [2, 4, 0];  // unsorted

removeValFromIndex.sort(function(a, b) { return b - a; }).forEach(function(index) {
  valuesArr.splice(index, 1);
});

This works well for me and work when deleting from an array of objects too:

var array = [ 
    { id: 1, name: 'bob', faveColor: 'blue' }, 
    { id: 2, name: 'jane', faveColor: 'red' }, 
    { id: 3, name: 'sam', faveColor: 'blue' }
];

// remove people that like blue

array.filter(x => x.faveColor === 'blue').forEach(x => array.splice(array.indexOf(x), 1));

There might be a shorter more effecient way to write this but this does work.


You can correct your code by replacing removeValFromIndex with removeValFromIndex.reverse(). If that array is not guaranteed to use ascending order, you can instead use removeValFromIndex.sort(function(a, b) { return b - a }).


Here's one possibility:

valuesArr = removeValFromIndex.reduceRight(function (arr, it) {
    arr.splice(it, 1);
    return arr;
}, valuesArr.sort(function (a, b) { return b - a }));

Example on jsFiddle

MDN on Array.prototype.reduceRight


If you are using underscore.js, you can use _.filter() to solve your problem.

var valuesArr = new Array("v1","v2","v3","v4","v5");
var removeValFromIndex = new Array(0,2,4);
var filteredArr = _.filter(valuesArr, function(item, index){
                  return !_.contains(removeValFromIndex, index);
                });

Additionally, if you are trying to remove items using a list of items instead of indexes, you can simply use _.without(), like so:

var valuesArr = new Array("v1","v2","v3","v4","v5");
var filteredArr = _.without(valuesArr, "V1", "V3");

Now filteredArr should be ["V2", "V4", "V5"]


filter + indexOf (IE9+):

function removeMany(array, indexes) {
  return array.filter(function(_, idx) {
    return indexes.indexOf(idx) === -1;
  });
}); 

Or with ES6 filter + find (Edge+):

function removeMany(array, indexes = []) {
  return array.filter((_, idx) => indexes.indexOf(idx) === -1)
}

Here's a quickie.

function removeFromArray(arr, toRemove){
    return arr.filter(item => toRemove.indexOf(item) === -1)
}

const arr1 = [1, 2, 3, 4, 5, 6, 7]
const arr2 = removeFromArray(arr1, [2, 4, 6]) // [1,3,5,7]

Quick ES6 one liner:

const valuesArr = new Array("v1","v2","v3","v4","v5");   
const removeValFromIndex = new Array(0,2,4);

const arrayWithValuesRemoved = valuesArr.filter((value, i) => removeValFromIndex.includes(i))

A simple and efficient (linear complexity) solution using filter and Set:

const valuesArr = ['v1', 'v2', 'v3', 'v4', 'v5'];   
const removeValFromIndex = [0, 2, 4];

const indexSet = new Set(removeValFromIndex);

const arrayWithValuesRemoved = valuesArr.filter((value, i) => !indexSet.has(i));

console.log(arrayWithValuesRemoved);

The great advantage of that implementation is that the Set lookup operation (has function) takes a constant time, being faster than nevace's answer, for example.


Sounds like Apply could be what you are looking for.
maybe something like this would work?

Array.prototype.splice.apply(valuesArray, removeValFromIndexes );

For Multiple items or unique item:

I suggest you use Array.prototype.filter

Don't ever use indexOf if you already know the index!:

var valuesArr = ["v1","v2","v3","v4","v5"];
var removeValFrom = [0, 2, 4];

valuesArr = valuesArr.filter(function(value, index) {
     return removeValFrom.indexOf(index) == -1;
}); // BIG O(N*m) where N is length of valuesArr and m is length removeValFrom

Do:

with Hashes... using Array.prototype.map

  var valuesArr = ["v1","v2","v3","v4","v5"];
  var removeValFrom = {};
  ([0, 2, 4]).map(x=>removeValFrom[x]=1); //bild the hash.
  valuesArr = valuesArr.filter(function(value, index) {
      return removeValFrom[index] == 1;
  }); // BIG O(N) where N is valuesArr;

var valuesArr = new Array("v1","v2","v3","v4","v5");   
var removeValFromIndex = new Array(0,2,4);

console.log(valuesArr)
let arr2 = [];

for (let i = 0; i < valuesArr.length; i++){
  if (    //could also just imput this below instead of index value
    valuesArr[i] !== valuesArr[0] && // "v1" <--
    valuesArr[i] !== valuesArr[2] && // "v3" <--
    valuesArr[i] !== valuesArr[4]    // "v5" <--
  ){
    arr2.push(valuesArr[i]);
  }
}

console.log(arr2);

This works. However, you would make a new array in the process. Not sure if thats would you want or not, but technically it would be an array containing only the values you wanted.


You could try and use delete array[index] This won't completely remove the element but rather sets the value to undefined.

참고URL : https://stackoverflow.com/questions/9425009/remove-multiple-elements-from-array-in-javascript-jquery

반응형