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

Posted

技术标签:

【中文标题】比较两个对象数组,并将匹配值的元素排除到JS中的新数组中【英文标题】:Comparing two arrays of objects, and exclude the elements who match values into new array in JS 【发布时间】:2016-01-03 02:50:17 【问题描述】:

这是我在 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 或下划线或类似的东西。

谢谢!

【问题讨论】:

分享您的研究对每个人都有帮助。告诉我们您尝试了什么以及为什么它不能满足您的需求。这表明您已经花时间尝试帮助自己,它使我们免于重复明显的答案,最重要的是它可以帮助您获得更具体和相关的答案!另见how to ask 自己探索:1, 2。 试试这个:***.com/questions/368280/… 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

在 lodash 中检查差异和异或。

【讨论】:

isArrayEqual(a1,a2);函数 isArrayEquals()【参考方案3】:

使用 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);
&lt;script src="https://cdn.jsdelivr.net/lodash/4.16.4/lodash.min.js"&gt;&lt;/script&gt;

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

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

希望对你有帮助。

【讨论】:

【参考方案4】:

好吧,这取决于具体情况。

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

【讨论】:

最后一行是整页中我最喜欢的一行! 这应该是最佳答案。单一、干净的线路,无需库。 这个答案不起作用!它返回公共元素而不是唯一元素。 要获取唯一元素而不是普通元素,请将最后一行更改为 let result = result1.filter(o1 =&gt; !result2.some(o2 =&gt; o1.id === o2.id)); 以返回相反的值 干净的答案,但它有 n^2 的复杂性【参考方案5】:

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

【讨论】:

简单明了的答案!【参考方案6】:

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

【讨论】:

以上是关于比较两个对象数组,并将匹配值的元素排除到JS中的新数组中的主要内容,如果未能解决你的问题,请参考以下文章

js使用Array.prototype.sort()对数组对象排序的方法

比较两个数组以查找匹配值的 for 循环

JS两个数组根据相同的ID进行重新组合数据?

如何实现两个数组之间值的替换

如何映射两个数组并将匹配作为按钮返回?

如何映射两个数组并将匹配项作为按钮返回?