다른 배열에 포함 된 모든 요소 제거


222

다른 배열에있는 경우 Javascript 배열에서 모든 요소를 ​​제거하는 효율적인 방법을 찾고 있습니다.

// If I have this array:
var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];

// and this one:
var toRemove = ['b', 'c', 'g'];

myArray에서 작동 하여이 상태를 유지하고 싶습니다. ['a', 'd', 'e', 'f']

jQuery와 함께 grep()and를 사용 하고 inArray()있습니다.

myArray = $.grep(myArray, function(value) {
    return $.inArray(value, toRemove) < 0;
});

루핑 및 스플 라이스 없이이 작업을 수행하는 순수한 자바 스크립트 방법이 있습니까?




1
가능한 중복 당신은 자바 스크립트 또는 jquery에서 하나의 배열을 다른 배열에서 제거 할 수 있습니다 -당신은 질문을 쓸 때 제안에 많은 관심을 지불 할 수 없습니다
mplungjan

어쨌든 항상 일정 수준의 루핑이 필요합니다.
푸른 하늘

진정으로 "효율적"이기를 원한다면과 같은 기능 유형 메소드를 사용하지 않을 것 .filter()입니다. 대신 for루프를 사용 합니다. .splice()원래 주문을 유지할 필요가없는 경우 피할 수 있습니다 . 또는 .splice()제거 할 항목이 많다고 생각하면 더 효율적 으로 만들 수있는 방법 이 있습니다.
푸른 하늘

답변:


379

Array.filter()방법을 사용하십시오 :

myArray = myArray.filter( function( el ) {
  return toRemove.indexOf( el ) < 0;
} );

브라우저 지원 Array.includes()이 증가함에 따라 약간의 개선이 이루어졌습니다 .

myArray = myArray.filter( function( el ) {
  return !toRemove.includes( el );
} );

화살표 기능을 사용한 다음 적응 :

myArray = myArray.filter( ( el ) => !toRemove.includes( el ) );

23
OP : Underscore.js를 사용 .difference()하는 경우 기본적으로 어떤 기능 이 있습니까 ?
Bill Criswell

내가 찾던 것. 감사합니다. @ BillCriswell, 밑줄을 확인할 것입니다.
탭하십시오

1
@AlecRust의 모든 요소 toRemove()를 대문자로 변환 하고 콜백을에서 el로 변경하십시오 el.toUpperCase().
Sirko

5
또는 더 짧은 :myArray = myArray.filter( el => !toRemove.includes( el ) );
538ROMEO

1
이 주문이 n ^ 2 아닙니까?
프레이저 커크 먼

34

filter방법은 트릭을 수행해야합니다.

const myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
const toRemove = ['b', 'c', 'g'];

// ES5 syntax
const filteredArray = myArray.filter(function(x) { 
  return toRemove.indexOf(x) < 0;
});

당신의 경우 toRemove 배열이 큰, 검색 패턴 이런 종류의 비효율적이 될 수 있습니다. 조회가 O(1)아닌 맵을 작성하는 것이 더 성능 이 좋습니다 O(n).

const toRemoveMap = toRemove.reduce(
  function(memo, item) {
    memo[item] = memo[item] || true;
    return memo;
  },
  {} // initialize an empty object
);

const filteredArray = myArray.filter(function (x) {
  return toRemoveMap[x];
});

// or, if you want to use ES6-style arrow syntax:
const toRemoveMap = toRemove.reduce((memo, item) => ({
  ...memo,
  [item]: true
}), {});

const filteredArray = myArray.filter(x => toRemoveMap[x]);

24

객체 배열을 사용하는 경우 그런 다음 아래 코드는 마술을 수행해야합니다. 여기서 객체 속성은 중복 항목을 제거하는 기준이됩니다.

아래 예에서는 각 항목의 이름을 비교하여 중복이 제거되었습니다.

이 예제를 시도하십시오. http://jsfiddle.net/deepak7641/zLj133rh/

var myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
var toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];

for( var i=myArray.length - 1; i>=0; i--){
 	for( var j=0; j<toRemove.length; j++){
 	    if(myArray[i] && (myArray[i].name === toRemove[j].name)){
    		myArray.splice(i, 1);
    	}
    }
}

alert(JSON.stringify(myArray));



11

ECMAScript 6 세트 는 두 배열의 다른 요소를 계산하는 데 사용할 수 있습니다.

const myArray = new Set(['a', 'b', 'c', 'd', 'e', 'f', 'g']);
const toRemove = new Set(['b', 'c', 'g']);

const difference = new Set([...myArray].filter((x) => !toRemove.has(x)));

console.log(Array.from(difference)); // ["a", "d", "e", "f"]


8

방금 다음과 같이 구현했습니다.

Array.prototype.exclude = function(list){
        return this.filter(function(el){return list.indexOf(el)<0;})
}

로 사용:

myArray.exclude(toRemove);

1
prototypes네이티브 객체 를 확장 하는 것은 좋지 않습니다 Array. 그것은 언어의 미래 발전과 장기적으로 충돌 할 수있다 ( 사례 참조flatten )
MarcoL

6

새로운 ES5를 사용할 수 없다면 filter두 개의 루프가 붙어 있다고 생각합니다.

for( var i =myArray.length - 1; i>=0; i--){
  for( var j=0; j<toRemove.length; j++){
    if(myArray[i] === toRemove[j]){
      myArray.splice(i, 1);
    }
  }
}

필터는 "새로운 HTML5 항목"이 아닙니다
goofballLogic

나는 "ES5 물건"을 써야했다. 5시
54 분에

6
var myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
var toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];



myArray = myArray.filter(ar => !toRemove.find(rm => (rm.name === ar.name && ar.place === rm.place) ))

잘받는 질문에 대한 설명을 추가해 주시겠습니까?
harmonica141

1
문제에 대한 해결책을 찾기 위해 몇 시간을 검색하고 방금 발견했습니다. 대단히 감사합니다!
Tarvo Mäesepp

5

이제 하나의 라이너 맛으로 :

console.log(['a', 'b', 'c', 'd', 'e', 'f', 'g'].filter(x => !~['b', 'c', 'g'].indexOf(x)))

오래된 브라우저에서는 작동하지 않을 수 있습니다.


3

lodash 에서 _.differenceBy를 사용할 수 있습니다

const myArray = [
  {name: 'deepak', place: 'bangalore'}, 
  {name: 'chirag', place: 'bangalore'}, 
  {name: 'alok', place: 'berhampur'}, 
  {name: 'chandan', place: 'mumbai'}
];
const toRemove = [
  {name: 'deepak', place: 'bangalore'},
  {name: 'alok', place: 'berhampur'}
];
const sorted = _.differenceBy(myArray, toRemove, 'name');

예제 코드 : CodePen


속성이 객체 안에 중첩되어 있으면 어떻게됩니까? 귀하의 경우 {name : 'deepak', 장소 : 'bangalore', 중첩 : {test : 1}}
Charith Jayasanka

2

가장 간단한 방법은 어떻습니까?

var myArray = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
var toRemove = ['b', 'c', 'g'];

var myArray = myArray.filter((item) => !toRemove.includes(item));
console.log(myArray)


2
명심 includesES7하기 전에 사용할 수 없습니다.
그렉

0

다른 배열에 포함 된 모든 요소를 ​​제거하는 올바른 방법은 요소 만 제거하여 소스 배열을 동일한 객체로 만드는 것입니다.

Array.prototype.removeContained = function(array) {
  var i, results;
  i = this.length;
  results = [];
  while (i--) {
    if (array.indexOf(this[i]) !== -1) {
      results.push(this.splice(i, 1));
    }
  }
  return results;
};

또는 CoffeeScript 해당 :

Array.prototype.removeContained = (array) ->
  i = @length
  @splice i, 1 while i-- when array.indexOf(@[i]) isnt -1

Chrome 개발자 도구 내부 테스트 :

19 : 33 : 04.447 a = 1
19 : 33 : 06.354 b = 2
19 : 33 : 07.615 c = 3
19 : 33 : 09.981 arr = [a, b, c]
19 : 33 : 16.460 arr1 = arr

19 : 33 : 20.317 arr1 === arr
19 : 33 : 20.331 true

19 : 33 : 43.592 arr.removeContained ([a, c])
19 : 33 : 52.433 arr === arr1
19 : 33 : 52.438 true

많은 수의 감시자와 다시로드없이 컬렉션을 업데이트 할 때 소스 개체에 대한 포인터를 유지하는 가장 좋은 방법은 Angular 프레임 워크를 사용하는 것입니다.


이 답변은 모범 사례가 무효화되어 좋지 않습니다. 특히 소유하지 않은 개체는 절대 수정하지 마십시오. 이 경우 Array 객체를 수정하는 것입니다.
하이브리드 웹 개발자

0

내장 방법을 사용하지 않고 논리를 작성합니다. 최적화 또는 수정 사항을 알려주십시오. JS 편집기에서 테스트했는데 정상적으로 작동합니다.

var myArray = [
            {name: 'deepak', place: 'bangalore'},
            {name: 'alok', place: 'berhampur'},
            {name: 'chirag', place: 'bangalore'},
            {name: 'chandan', place: 'mumbai'},

        ];
        var toRemove = [

            {name: 'chirag', place: 'bangalore'},
            {name: 'deepak', place: 'bangalore'},
            /*{name: 'chandan', place: 'mumbai'},*/
            /*{name: 'alok', place: 'berhampur'},*/


        ];
        var tempArr = [];
        for( var i=0 ; i < myArray.length; i++){
            for( var j=0; j<toRemove.length; j++){
                var toRemoveObj = toRemove[j];
                if(myArray[i] && (myArray[i].name === toRemove[j].name)) {
                    break;
                }else if(myArray[i] && (myArray[i].name !== toRemove[j].name)){
                        var fnd = isExists(tempArr,myArray[i]);
                        if(!fnd){
                            var idx = getIdex(toRemove,myArray[i])
                            if (idx === -1){
                                tempArr.push(myArray[i]);
                            }

                        }

                    }

                }
        }
        function isExists(source,item){
            var isFound = false;
            for( var i=0 ; i < source.length; i++){
                var obj = source[i];
                if(item && obj && obj.name === item.name){
                    isFound = true;
                    break;
                }
            }
            return isFound;
        }
        function getIdex(toRemove,item){
            var idex = -1;
            for( var i=0 ; i < toRemove.length; i++){
                var rObj =toRemove[i];
                if(rObj && item && rObj.name === item.name){
                    idex=i;
                    break;
                }
            }
            return idex;
        }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.