减去数组 - javascript

bsa*_*mur 7 javascript arrays

我有阵列像;

var john = { name: "John Smith", age: 23 };
var mary = { name: "Mary Key", age: 18 };
var bob = { name: "Bob-small", age: 6 };
var people = [john, mary, bob];

var john2 = { name: "John Smith", age: 23 };
var people2 = [john2];
Run Code Online (Sandbox Code Playgroud)

我想做的是从人们中减去people2并获得结果;

[mary, bob];
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?TIA

Tib*_*bos 5

这是一个简单的解决方案:

var diff = people.filter(function(item) {
  return !people2.some(function(test){
    return test.name === item.name && test.age === item.age;
  });
});
Run Code Online (Sandbox Code Playgroud)

确保传递给的函数people2.some正确检查两个对象是否相等,因为==会失败,因为您引用了具有相同属性的不同对象。


Aad*_*hah 5

你需要的第一件事就是比较两个人的数学等价.我们不能使用===运算符,因为它测试两个对象的标识等价,而不是数学等价.例如:

var john = {name: "John Smith", age: 23};
var john2 = {name: "John Smith", age: 23};

console.log(john === john2); // false
Run Code Online (Sandbox Code Playgroud)

因此我们创建了一个比较两个人的功能:

console.log(similarPeople(john, john2));

function similarPeople(a, b) {
    return a.name === b.name &&
           a.age === b.age;
}
Run Code Online (Sandbox Code Playgroud)

函数被命名的原因similarPeople不是samePeople因为两个不同的人可能具有相同的名称并且可能具有相同的年龄.


两组A和B的差异被定义为A中所有那些不在B中的元素的集合.

在最坏的情况计算的两组,A和B,尺寸的差集mn分别将采取O(m * n)时间.效率不高:

function difference(a, b, eq) {
    if (arguments.length < 3) eq = function (a, b) {
        return a === b;
    };

    var m = a.length;
    var n = b.length;

    var c = [];

    loop: for (var i = 0; i < m; i++) {
        var x = a[i];

        for (var j = 0; j < n; j++)
            if (eq(b[j], x))
                continue loop;

        c.push(x);
    }

    return c;
}
Run Code Online (Sandbox Code Playgroud)

现在你可以得到两个人名单的区别如下:

var people = [john, mary, bob];
var people2 = [john2];

console.log(difference(people, people2, similarPeople)); // [mary, bob]
Run Code Online (Sandbox Code Playgroud)

请参阅演示:http://jsfiddle.net/F7RDs/


幸运的是,有一种更快的方法来计算大型集合的集合差异:指数.让我们创建一个函数来创建人员列表的索引:

function indexFrom(people) {
    var length = people.length, index = {};

    for (var i = 0; i < length; i++) {
        var person = people[i];
        var name = person.name;

        if (index.hasOwnProperty(name)) var subindex = index[name];
        else var subindex = index[name] = {};
        subindex[person.age] = {};
    }

    return index;
}
Run Code Online (Sandbox Code Playgroud)

现在我们为第二个人列表创建一个索引:

var index2 = indexFrom(people2);
Run Code Online (Sandbox Code Playgroud)

我们还需要一个函数来测试一个人是否在使用其索引的列表中:

function hasPerson(person, index) {
    var name = person.name;

    return index.hasOwnProperty(name) &&
           index[name].hasOwnProperty(person.age);
}
Run Code Online (Sandbox Code Playgroud)

最后,我们可以创建一个更有效的实现,difference如下所示:

function difference(a, index, has) {
    var m = a.length, c = [];

    for (var i = 0; i < m; i++) {
        var x = a[i];
        if (!has(x, index))
            c.push(x);
    }

    return c;
}
Run Code Online (Sandbox Code Playgroud)

您可以按如下方式使用它:

console.log(difference(people, index2, hasPerson)); // [mary, bob]
Run Code Online (Sandbox Code Playgroud)

优点是创建索引需要O(n)时间并且计算差异需要O(m)时间.因此总的来说,它只需要O(m + n)时间而不是O(m * n)时间.此外,您可以缓存索引以供将来使用.

请参阅演示:http://jsfiddle.net/F7RDs/1/

希望这有帮助.