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

这是我在 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

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


【解决方案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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-02
        • 1970-01-01
        • 1970-01-01
        • 2019-01-04
        • 1970-01-01
        • 1970-01-01
        • 2018-05-18
        • 1970-01-01
        相关资源
        最近更新 更多