Comparing two arrays of objects, and exclude the elements who match values into new array in JS

时间:2015-10-06 08:54:56

标签: javascript arrays underscore.js javascript-objects lodash

here is my use case in JavaScript:

I have two arrays of objects which have properties that match (id & name).

var result1 = [
    {id:1, name:'Sandra', type:'user', username:'sandra'},
    {id:2, name:'John', type:'admin', username:'johnny2'},
    {id:3, name:'Peter', type:'user', username:'pete'},
    {id:4, name:'Bobby', type:'user', username:'be_bob'}
];

var result2 = [
    {id:2, name:'John', email:'johnny@example.com'},
    {id:4, name:'Bobby', email:'bobby@example.com'}
];

var props = ['id', 'name'];

My goal is to have another array of objects containing only the elements which did not match. Like this:

var result = [
    {id:1, name:'Sandra'},
    {id:3, name:'Peter'}
];

I know that there is a way of doing this by going from result1 compare each object with the objects of result2, then compare their keys, and if did'n match, put the values in another object then push it in new array, but I wonder is there any more elegant way, like using lo-dash or underscore or something similar.

Thank you!

6 个答案:

答案 0 :(得分:34)

只需使用内置于JS中的Array iteration methods即可:



var result1 = [
    {id:1, name:'Sandra', type:'user', username:'sandra'},
    {id:2, name:'John', type:'admin', username:'johnny2'},
    {id:3, name:'Peter', type:'user', username:'pete'},
    {id:4, name:'Bobby', type:'user', username:'be_bob'}
];

var result2 = [
    {id:2, name:'John', email:'johnny@example.com'},
    {id:4, name:'Bobby', email:'bobby@example.com'}
];

var props = ['id', 'name'];

var result = result1.filter(function(o1){
    // filter out (!) items in result2
    return !result2.some(function(o2){
        return o1.id === o2.id;          // assumes unique id
    });
}).map(function(o){
    // use reduce to make objects with only the required properties
    // and map to apply this to the filtered array as a whole
    return props.reduce(function(newo, name){
        newo[name] = o[name];
        return newo;
    }, {});
});

document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 4) +
        '</pre>';
&#13;
&#13;
&#13;

如果您正在做很多事情,那么请务必查看外部图书馆来帮助您,但是首先要学习基础知识,并且基础知识将为您提供良好的服务。

答案 1 :(得分:22)

好吧,这使用lodash或vanilla javascript取决于具体情况。

但是只返回包含重复数据的数组,可以通过以下方式实现,当然它来自@ 1983

var result = result1.filter(function (o1) {
    return result2.some(function (o2) {
        return o1.id === o2.id; // return the ones with equal id
   });
});
// if you want to be more clever...
let result = result1.filter(o1 => result2.some(o2 => o1.id === o2.id));

答案 2 :(得分:10)

使用Lodash可以获得相同的结果。

&#13;
&#13;
var result1 = [
    {id:1, name:'Sandra', type:'user', username:'sandra'},
    {id:2, name:'John', type:'admin', username:'johnny2'},
    {id:3, name:'Peter', type:'user', username:'pete'},
    {id:4, name:'Bobby', type:'user', username:'be_bob'}
];

var result2 = [
    {id:2, name:'John', email:'johnny@example.com'},
    {id:4, name:'Bobby', email:'bobby@example.com'}
];

var result3 = _(result1) 
        .differenceBy(result2, 'id', 'name')
        .map(_.partial(_.pick, _, 'id', 'name'))
        .value();

console.log(result3);
&#13;
<script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"></script>
&#13;
&#13;
&#13;

您可以使用属性&#34; id&#34;来获取所需的结果,并应用两个数组之间的差异。和&#34;名称&#34;作为一种方式来链接&#34;他们之间的元素。如果这些属性中的任何一个不同,则元素被认为是不同的(在您的情况下不可能,因为id似乎是唯一的)。

最后,您必须映射结果,以便省略&#34;省略&#34;对象的不受欢迎的属性。

希望它有所帮助。

答案 3 :(得分:7)

我已经搜索了很多解决方案,我可以在其中比较具有不同属性名称的两个对象数组(类似于左外连接)。我想出了这个解决方案。我在这里使用了Lodash。我希望这能帮到您。

var Obj1 = [
    {id:1, name:'Sandra'},
    {id:2, name:'John'},   
];

var Obj2 = [
    {_id:2, name:'John'},
    {_id:4, name:'Bobby'}
];

var Obj3 = lodash.differenceWith(Obj1, Obj2, function (o1, o2) {
    return o1['id'] === o2['_id']
});

console.log(Obj3);
//  {id:1, name:'Sandra'}

答案 4 :(得分:2)

查看lodash中的差异和xor。

答案 5 :(得分:0)

以下是使用Lodash的另一种解决方案:

var _ = require('lodash');

var result1 = [
    {id:1, name:'Sandra', type:'user', username:'sandra'},
    {id:2, name:'John', type:'admin', username:'johnny2'},
    {id:3, name:'Peter', type:'user', username:'pete'},
    {id:4, name:'Bobby', type:'user', username:'be_bob'}
];

var result2 = [
    {id:2, name:'John', email:'johnny@example.com'},
    {id:4, name:'Bobby', email:'bobby@example.com'}
];

// filter all those that do not match
var result = types1.filter(function(o1){
    // if match found return false
    return _.findIndex(types2, {'id': o1.id, 'name': o1.name}) !== -1 ? false : true;
});

console.log(result);