我有阵列像;
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
这是一个简单的解决方案:
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正确检查两个对象是否相等,因为==会失败,因为您引用了具有相同属性的不同对象。
你需要的第一件事就是比较两个人的数学等价.我们不能使用===运算符,因为它测试两个对象的标识等价,而不是数学等价.例如:
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,尺寸的差集m和n分别将采取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/
希望这有帮助.