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

IT技术 javascript arrays underscore.js javascript-objects lodash
2021-01-20 05:59:27

这是我在 JavaScript 中的用例:

我有两个对象数组,它们的属性匹配(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:'johnny@example.com'},
    {id:4, name:'Bobby', email:'bobby@example.com'}
];

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

我的目标是让另一个对象数组只包含不匹配的元素。像这样:

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

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

谢谢!

6个回答

好吧,这使用 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));
干净的答案,但它有 n^2 复杂性
2021-03-16 05:59:27
这个答案不起作用!它返回公共元素而不是唯一元素。
2021-03-26 05:59:27
要获取唯一元素而不是常见元素,请将最后一行更改let result = result1.filter(o1 => !result2.some(o2 => o1.id === o2.id));为返回相反的值
2021-03-31 05:59:27
这应该是最佳答案。单一、干净的生产线,不需要库。
2021-04-02 05:59:27
最后一行是我在整个页面中最喜欢的一行!
2021-04-04 05:59:27

只需使用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:'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>';

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

使用 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'}
];

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>

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

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

希望能帮助到你。

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

这是使用 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);