JavaScript中移除数组中的另一个数组

30

假设我们有以下数组:

a = [1, 2, 3, 4, 5]

b = [2, 3]

我该如何从a中减去b?使得我们有c = a - b,它应该等于[1, 4, 5]。jQuery的解决方案也可以。


这个回答解决了你的问题吗?[从另一个数组中删除所有包含的元素] (https://dev59.com/_mIj5IYBdhLWcg3wuHTP) - Heretic Monkey
6个回答

46

假设你使用的浏览器支持 Array.prototype.filterArray.prototype.indexOf,你可以使用以下代码:

var c = a.filter(function(item) {
    return b.indexOf(item) === -1;
});

如果所使用的浏览器没有这些方法,您可以尝试进行Shim(填充)。


2
顺便提一下,IE8是市场上唯一没有实现这些方法的相关浏览器...来源:http://kangax.github.com/es5-compat-table/ - Šime Vidas
1
@Kakashi:对我来说可以。你用的是哪个版本? - icktoofay
请注意,上面的链接包含用于 filter 和 indexOf 的 shim。 - Grinn

11

这是 @icktoofay 发布的答案的修改版本。

在 ES6 中,我们可以使用:

这将简化我们的代码为:

var c = a.filter(x => !b.includes(x));

演示:

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var c = a.filter(x => !b.includes(x));
console.log(c);


3

要让代码在所有浏览器中都能正常运行,您需要手动查找a中的每个元素并将其从b中删除。

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

var result = [], found;
for (var i = 0; i < a.length; i++) {
    found = false;
    // find a[i] in b
    for (var j = 0; j < b.length; j++) {
        if (a[i] == b[j]) {
            found = true;
            break;
        }
    }
    if (!found) {
        result.push(a[i]);
    }
}
// The array result now contains just the items from a that are not in b

以下是一个工作示例:http://jsfiddle.net/jfriend00/xkBzR/

此外,这里还有一个版本,适用于大型数组,因为它将所有内容放入对象中进行哈希查找,而不是使用 brute force 数组搜索,这可能会更快:

var a = [1, 2, 3, 4, 5];
var b = [2, 3];

function filterArray(src, filt) {
    var temp = {}, i, result = [];
    // load contents of filt into object keys for faster lookup
    for (i = 0; i < filt.length; i++) {
        temp[filt[i]] = true;
    }

    // go through src
    for (i = 0; i < src.length; i++) {
        if (!(src[i] in temp)) {
            result.push(src[i]);
        }
    }
    return(result);
}

var filtered = filterArray(a, b);

这里有一个实际工作的例子:http://jsfiddle.net/jfriend00/LUcx6/


为什么不实现 Array.filter 方法呢?在其他情况下也可能非常有用。 - Kakashi
Array.filter() 很有用 - 我只是提供了一种替代方法。有些人不想向现有的核心对象添加方法,或者他们的代码可能会因此而中断。 - jfriend00

2

如果你在处理像日期这样的对象时遇到困难,你会发现即使它们具有相同的值,两个不同的对象也永远不会相等,所以上面的答案是不起作用的。 以下是ES6解决此问题的答案。

const c = a.filter(aObject => b.findIndex(bObject => aObject.valueOf() === bObject.valueOf()) === -1)

0
这里是一个适用于所有浏览器的try实现方式:
if('filter' in Array == false) {
    Array.prototype.filter = 
        function(callback) {
            if(null == this || void 0 == this) {
                return;
             }
            var filtered = [];
            for(i = 0, len = this.length; i < len; i++) {
                    var tmp = this[i];
                    if(callback(tmp)) {
                        filtered.push(tmp);
                     }
             }
                return filtered;
       }
  }

a = [1, 2, 3, 4, 5]; 
b = [2, 3]; 

var c = a.filter(function(item) { /*implementation of icktoofay */
    return b.indexOf(item) === -1;
});

Array.indexOf在所有浏览器中都不存在(例如,在IE9之前的任何版本中都不存在)。 - jfriend00

0

这个问题可能有点过时,但我认为对某些人可能仍然有用。

let first = [1,2,3,4,5,6,7,9];
let second = [2,4,6,8];
const difference = first.filter(item=>!second.includes(item));
console.log(difference);//[ 1, 3, 6,7]
/*
the above will not work for objects with properties
This might do the trick
*/
const firstObj = [{a:1,b:2},{a:3,b:4},{a:5,b:6},{a:7,b:8}]//not ideal. I know
const secondObj = [{a:3,b:4},{a:7,b:8}]

const objDiff = firstObj.filter(obj=>
  !secondObj.find(sec=>//take note of the "!"
    sec.a===obj.a
    &&//or use || if you want to check for either or
    sec.b===obj.b
  )//this is formatted so that it is easily readable
);
console.log(objDiff)/*
[
  {
    "a": 1,
    "b": 2
  },
  {
    "a": 5,
    "b": 6
  }
]
*/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接