减去数组 - javascript

时间:2014-02-02 10:28:09

标签: 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];

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

[mary, bob];

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

3 个答案:

答案 0 :(得分:5)

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

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

console.log(john === john2); // false

因此我们创建了一个比较两个人的函数:

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

function similarPeople(a, b) {
    return a.name === b.name &&
           a.age === b.age;
}

该函数名为similarPeople而不是samePeople的原因是因为两个不同的人可能具有相同的名称且可能具有相同的年龄。


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

在最坏的情况下,计算大小为mn的两组A和B的集合差异将花费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;
}

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

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

console.log(difference(people, people2, similarPeople)); // [mary, bob]

请参阅演示: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;
}

现在我们为第二个人名单创建一个索引:

var index2 = indexFrom(people2);

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

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

    return index.hasOwnProperty(name) &&
           index[name].hasOwnProperty(person.age);
}

最后,我们可以创建一个更有效的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;
}

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

console.log(difference(people, index2, hasPerson)); // [mary, bob]

优点是创建索引需要O(n)次,计算差异需要O(m)次。因此,总共只需O(m + n)次,而不是O(m * n)次。此外,您可以缓存索引以供将来使用。

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

希望这会有所帮助。

答案 1 :(得分:3)

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

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

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

答案 2 :(得分:0)

所以,这里是最终运行的代码。复制,粘贴并检查输出。首先是分隔字符串(逗号分隔)。然后它是单独比较它们。请检查此链接:http://jsfiddle.net/DXRZ4/

<html>
  <head>
    <script>
        var a = new Array(); var i=1; var people = new Array();
        function fun() {
            var str = "john,john,bob",
                l = str.split(",");
            for(i=0; i<3; i++) {
                a[i] = l[i];
                // this will show the comma separated strings
                document.writeln(l[i]);
            }
            for(i=0; i<3; i++) {
                t=a[i]; 
                j=a[i+1];
                if((a[i]==a[i+1]) || (a[i]==a[i+2])) {
                    // it will store the position of string which are same
                    p=i; 
                }
            }
            for(i=0; i<3; i++) { 
                if(p!=i){
                    document.writeln("Subtracted Strings are:-");
                    document.writeln(l[i]);
                }
            }
        }
    </script>
  <body>
    <input type="button" name="b1" onClick="fun()">
  </body>
</html>