[javascript] 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)

이것은 중간에서 시작으로 요소를 제거하므로 제거 할 때마다 js 엔진이 n/2요소 를 복사하도록 강제합니다 (n/2)^2. 총 복사 작업은 2 차입니다.

스플 라이스 솔루션 ( is오버 헤드를 제거하기 위해 이미 내림차순으로 정렬 되었다고 가정 )은 다음과 같습니다.

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

그러나 처음부터 배열을 재구성하고 마스크를 사용하여 요소를 복사하는지 여부를 확인하여 선형 시간 솔루션을 구현하는 것은 어렵지 않습니다 (정렬은이를로 푸시합니다 O(n)log(n)). 다음은 그러한 구현입니다 ( mask속도를 위해 부울 반전 되지 않음 ).

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

나는 이것을 jsperf.com 에서 실행 했고 심지어 n=100스플 라이스 방법도 완전히 90 % 느리다. 더 클수록 n이 차이는 훨씬 더 클 것입니다.