Javascript 比较两个对象数组,在JS中排除匹配值的元素到新数组中

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32965688/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 14:26:48  来源:igfitidea点击:

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

javascriptarraysunderscore.jsjavascript-objectslodash

提问by Leo

here is my use case in JavaScript:

这是我在 JavaScript 中的用例:

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

我有两个对象数组,它们的属性匹配(id 和名称)。

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:'[email protected]'},
    {id:4, name:'Bobby', email:'[email protected]'}
];

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.

我知道有一种方法可以通过从 result1 将每个对象与 result2 的对象进行比较,然后比较它们的键,如果不匹配,则将值放入另一个对象中,然后将其推入新数组中,但是我想知道有没有更优雅的方法,比如使用 lo-dash 或下划线或类似的东西。

Thank you!

谢谢!

回答by 1983

Just using the Array iteration methodsbuilt into JS is fine for this:

只需使用JS 内置的Array 迭代方法就可以了:

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:'[email protected]'},
    {id:4, name:'Bobby', email:'[email protected]'}
];

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>';

If you are doing this a lot, then by all means look at external libraries to help you out, but it's worth learning the basics first, and the basics will serve you well here.

如果你经常这样做,那么一定要看看外部库来帮助你,但首先学习基础知识是值得的,基础知识在这里会很好地为你服务。

回答by blackend

well, this using lodash or vanilla javascript it depends on the situation.

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

but for just return the array that contains the duplicates it can be achieved by the following, offcourse it was taken from @1983

但是为了只返回包含重复项的数组,它可以通过以下方式实现,当然它取自@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));

回答by acontell

The same result can be achieved using Lodash.

使用 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:'[email protected]'},
    {id:4, name:'Bobby', email:'[email protected]'}
];

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

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

You can get the desired result applying a difference between both arrays using the properties "id" and "name" as a way to "link" elements between them. If any of those properties are different, the elements are considered different (improbably in your case because id seems to be unique).

您可以使用属性“id”和“name”作为在它们之间“链接”元素的方式,应用两个数组之间的差异来获得所需的结果。如果这些属性中的任何一个不同,则元素被认为是不同的(在您的情况下不太可能,因为 id 似乎是唯一的)。

Lastly, you have to map the result in order to "omit" the undesired properties of the object.

最后,您必须映射结果以“省略”对象的不需要的属性。

Hope it helps.

希望能帮助到你。

回答by apurvasharma

I have searched a lot for a solution in which I can compare two array of objects with different attribute names (something like a left outer join). I came up with this solution. Here I used Lodash. I hope this will help you.

我已经搜索了很多解决方案,在该解决方案中我可以比较具有不同属性名称的两个对象数组(类似于左外连接)。我想出了这个解决方案。这里我使用了 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'}

回答by Prasad Thammineni

Here is another solution using Lodash:

这是使用 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:'[email protected]'},
    {id:4, name:'Bobby', email:'[email protected]'}
];

// 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);

回答by jedierikb

Check out difference and xor in lodash.

查看 lodash 中的差异和异或。