Javascript数组:删除另一个数组中包含的所有元素

时间:2013-11-13 15:13:40

标签: javascript jquery arrays

我正在寻找一种有效的方法来删除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()inArray(),效果很好:

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

在没有循环和拼接的情况下,是否有一种纯粹的javascript方法可以做到这一点?

15 个答案:

答案 0 :(得分:262)

使用Array.filter()方法:

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

随着对Array.includes()的浏览器支持的增加,小改进:

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

使用arrow functions进行下一次调整:

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

答案 1 :(得分:25)

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]);

答案 2 :(得分:20)

如果您使用的是对象数组。然后下面的代码应该做魔术,其中对象属性将是删除重复项的标准。

在下面的示例中,删除了重复项,并比较了每个项目的名称。

试试这个例子。 http://jsfiddle.net/deepak7641/zLj133rh/

session.getId()

答案 3 :(得分:8)

Lodash还有一个实用功能: https://lodash.com/docs#difference

答案 4 :(得分:8)

ECMAScript 6 sets可用于计算两个数组的不同元素:

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"]

答案 5 :(得分:6)

我刚刚实现了:

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

用作:

myArray.exclude(toRemove);

答案 6 :(得分:5)

如果你不能使用新的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);
    }
  }
}

答案 7 :(得分:3)

现在采用单线风格:

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

可能无法在旧版浏览器上使用。

答案 8 :(得分: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

答案 9 :(得分: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)

答案 10 :(得分:0)

删除另一个数组中包含的所有元素的正确方法是通过仅删除元素来使源数组成为同一对象:

dataset = dataset.map(parse_function_wrapper,
                  num_parallel_calls=4)
dataset = dataset.batch(32)

或CoffeeScript等效项:

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;
};

在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是

     

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

使用Angular框架是在更新集合时保持指针指向源对象的最佳方法,而无需大量观察者和重新加载。

答案 11 :(得分: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;
        }

答案 12 :(得分:0)

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

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

答案 13 :(得分:0)

如果您使用的是Typescript,并且希望匹配单个属性值,则该方法应基于上面的Craciun Ciprian's answer

您还可以通过允许非对象匹配和/或多属性值匹配来使其更通用。

/**
 *
 * @param arr1 The initial array
 * @param arr2 The array to remove
 * @param propertyName the key of the object to match on
 */
function differenceByPropVal<T>(arr1: T[], arr2: T[], propertyName: string): T[] {
  return arr1.filter(
    (a: T): boolean =>
      !arr2.find((b: T): boolean => b[propertyName] === a[propertyName])
  );
}

答案 14 :(得分:0)

这已经很晚了,但添加此内容是为了解释 @mojtaba roohi 的回答。第一个代码块将不起作用,因为每个数组都有不同的对象,即 df[0] != nfl[2]。这两个对象看起来相似但完全不同,当我们使用像数字这样的原始类型时,情况并非如此。

let df = [ {'name': 'C' },{'name': 'D' }] 
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }] 
let res = nfl.filter(x => df.indexOf(x)<0)
console.log(res)

这是工作代码:

let df = [{'name': 'C' },{'name': 'D' }]
let nfl = [ {'name': 'A' },{'name': 'B' },{'name': 'C' },{'name': 'D' }];
let res = nfl.filter((o1) => !df.some((o2) => o1.name === o2.name));
console.log(res)