如何在 es6 中仅比较和过滤两个对象数组中不匹配的数组

Posted

技术标签:

【中文标题】如何在 es6 中仅比较和过滤两个对象数组中不匹配的数组【英文标题】:How to compare and filter only unmatched arrays from two array of objects in es6 【发布时间】:2020-04-24 23:55:02 【问题描述】:

在我的 Angular 应用程序中,我试图仅获取从 UI 修改的更新数组。

在这里,我有两个数组,其中一个角色名称已更改。我想比较并过滤掉修改过的对象,只返回那些修改过的数组。 (在这种情况下,role_name 值被修改)

我尝试在 ES6 的帮助下进行过滤,但它不起作用。

有人可以帮我解决我在哪里失踪吗?

var arr1 = [ 
  "num" : null,
  "role_name" : "ABC",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "1",
  "user_name" : "Rywan"
,

  "num" : null,
  "role_name" : "DEF",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "2",
  "user_name" : "adecg"
,

  "num" : null,
  "role_name" : "GHJ",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "3",
  "user_name" : "dde"
,

  "num" : null,
  "role_name" : "RRT",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "4",
  "user_name" : "kumar"
,

  "num" : null,
  "role_name" : "SFR",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "5",
  "user_name" : "SASI"

];

var arr2 = [ 
  "num" : null,
  "role_name" : "ABC",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "1",
  "user_name" : "Rywan"
,

  "num" : null,
  "role_name" : "ROLE_CHANGED",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "2",
  "user_name" : "adecg"
,

  "num" : null,
  "role_name" : "GHJ",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "3",
  "user_name" : "dde"
,

  "num" : null,
  "role_name" : "RRT",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "4",
  "user_name" : "kumar"
,

  "num" : null,
  "role_name" : "SFR",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "5",
  "user_name" : "SASI"

];

   let filteredData;
     filteredData = arr1.filter(function(o1)
      //filter out (!) items in arr2
       return arr2.some(function(o2)
           return o1.role_name !== o2.role_name;  
      );
   );
   
   console.log(filteredData);

输出应该是

[

      "num" : null,
      "role_name" : "ROLE_CHANGED",
      "profile" : "ff",
      "user" : "1234",
      "rn" : "2",
      "user_name" : "adecg"
    
]

【问题讨论】:

如果预计两个数组中元素的顺序相同,则可以执行以下操作:const filteredData = arr2.filter((item, index) => item.role_name !== arr1[index].role_name); 你可以使用下划线库***.com/questions/28632281/… 【参考方案1】:

我们已有的解决方案有点不同。

Object.keys() 使用filter() 时,如果值已更改为arr1[index].role_name !== arr2[index].role_name,我们还可以根据数组的索引比较role_name 属性。这将返回我们已更改值的数组的所有索引。然后使用map() 根据找到的数组键为这些元素生成一个新数组。

所以解决办法是:

Object.keys(arr1).filter(index => arr1[index].role_name !== arr2[index].role_name)
                 .map(index => arr2[index]);

Object.keys():

Object.keys() 方法返回一个给定对象自己的可枚举属性名称的数组,其顺序与我们在正常循环中得到的顺序相同。

Array.prototype.filter():

filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

Array.prototype.map():

map() 方法创建一个新数组,其中填充了对调用数组中的每个元素调用提供的函数的结果。

我认为您可以尝试以下方法:

const arr1 = [
  "num" : null,
  "role_name" : "ABC",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "1",
  "user_name" : "Rywan"
,

  "num" : null,
  "role_name" : "DEF",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "2",
  "user_name" : "adecg"
,

  "num" : null,
  "role_name" : "GHJ",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "3",
  "user_name" : "dde"
,

  "num" : null,
  "role_name" : "RRT",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "4",
  "user_name" : "kumar"
,

  "num" : null,
  "role_name" : "SFR",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "5",
  "user_name" : "SASI"
];

const arr2 = [
  "num" : null,
  "role_name" : "ABC",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "1",
  "user_name" : "Rywan"
,

  "num" : null,
  "role_name" : "ROLE_CHANGED",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "2",
  "user_name" : "adecg"
,

  "num" : null,
  "role_name" : "GHJ",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "3",
  "user_name" : "dde"
,

  "num" : null,
  "role_name" : "RRT",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "4",
  "user_name" : "kumar"
,

  "num" : null,
  "role_name" : "SFR",
  "profile" : "ff",
  "user" : "1234",
  "rn" : "5",
  "user_name" : "SASI"
];

const changedObjects = Object.keys(arr1).filter(index => arr1[index].role_name !== arr2[index].role_name)
                                        .map(index => arr2[index]);
   
console.log(changedObjects);

希望对你有帮助!

【讨论】:

【参考方案2】:

您的逻辑有点缺陷,因为您的 .some() 将始终返回 true,因为总有一个元素会有所不同。您要做的是实际检查任何一个角色名称是否相同。如果没有找到匹配项(即.some() 返回 false),那么您就知道 role_name 已更改:

const filteredData = arr2.filter((o1, i) => 
  return !arr1.some((o2) => 
    return o1.role_name === o2.role_name;
  );
);

var arr1 = [
    "num": null,
    "role_name": "ABC",
    "profile": "ff",
    "user": "1234",
    "rn": "1",
    "user_name": "Rywan"
  ,
  
    "num": null,
    "role_name": "DEF",
    "profile": "ff",
    "user": "1234",
    "rn": "2",
    "user_name": "adecg"
  ,
  
    "num": null,
    "role_name": "GHJ",
    "profile": "ff",
    "user": "1234",
    "rn": "3",
    "user_name": "dde"
  ,
  
    "num": null,
    "role_name": "RRT",
    "profile": "ff",
    "user": "1234",
    "rn": "4",
    "user_name": "kumar"
  ,
  
    "num": null,
    "role_name": "SFR",
    "profile": "ff",
    "user": "1234",
    "rn": "5",
    "user_name": "SASI"
  
];

var arr2 = [
    "num": null,
    "role_name": "ABC",
    "profile": "ff",
    "user": "1234",
    "rn": "1",
    "user_name": "Rywan"
  ,
  
    "num": null,
    "role_name": "ROLE_CHANGED",
    "profile": "ff",
    "user": "1234",
    "rn": "2",
    "user_name": "adecg"
  ,
  
    "num": null,
    "role_name": "GHJ",
    "profile": "ff",
    "user": "1234",
    "rn": "3",
    "user_name": "dde"
  ,
  
    "num": null,
    "role_name": "RRT",
    "profile": "ff",
    "user": "1234",
    "rn": "4",
    "user_name": "kumar"
  ,
  
    "num": null,
    "role_name": "SFR",
    "profile": "ff",
    "user": "1234",
    "rn": "5",
    "user_name": "SASI"
  
];

const filteredData = arr2.filter((o1, i) => 
  return !arr1.some((o2) => 
    return o1.role_name === o2.role_name;
  );
);

console.log(filteredData);

【讨论】:

太棒了!我的逻辑是问题

以上是关于如何在 es6 中仅比较和过滤两个对象数组中不匹配的数组的主要内容,如果未能解决你的问题,请参考以下文章

如何从mysql数据库表中仅获取php数组的匹配项[重复]

循环遍历两个对象数组以将匹配值推送到新数组在 React 中不起作用,但在 JS Fiddle 中起作用

如何从 React 中的对象数组中仅返回 3 个元素

从数组中过滤对象,具有匹配两个值的差异

比较两个对象数组并在新数组中返回匹配值

数组对象去重