【问题标题】:compare and filter 2 arrays比较和过滤 2 个数组
【发布时间】:2021-08-31 19:50:23
【问题描述】:

我有 2 个数组。我只需要显示与第二个数组不匹配的数据。

array1 = [
  {
    country: "usa", 
    child: [
      { id: 1, name: "fvsdfsd"   },
      { id: 2, name: "hhghhhfhj" },
    ],
  },
  {
    country: "CA", 
    child: [
      { id: 3, name: "adsada"    },
      { id: 4, name: "hhghhhfhj" },
    ],
  },
  {
    country: "AU",
    child: [
      { id: 5, name: "seven"     },
      { id: 6, name: "hhghhhfhj" },
    ],
  },
];

array2 = [
  { id: 1, name: "fvsdfsd"   },
  { id: 2, name: "hhghhhfhj" },
];

结果:

[
  {
    country: "usa", 
    child: [],
  },
  {
    country: "CA", 
    child: [
     { id: 3, name: "adsada"    },
     { id: 4, name: "hhghhhfhj" },
    ],
  },
  {
    country: "AU",
    child: [
      { id:5, name: "seven"     },
      { id:6, name: "hhghhhfhj" },
    ],
  },
]

我尝试这样,但它不起作用

array1.filter(data => !array2.includes(data.child));

【问题讨论】:

  • 仅供参考,您的数组不是有效的 javascript 数组。

标签: javascript angular typescript ecmascript-6


【解决方案1】:

由于 Ecma/Javascript 执行相等性测试的方式,您的代码无法正常工作。 Array.includes() 使用 sameValueZero 算法来确定两个事物是否“相等”。

[Javascript 中的相等性很奇怪]

对象比较是通过reference完成的,所以两个对象相等当(且仅当)它们在内存中是完全相同的对象。比如

const areEqual = {a:1,b:2} === {a:1,b:2}

是false,原样

const areEqual = {a:1,b:2} == {a:1,b:2}

您需要深度相等检查类似 lodash 的 isEqual():

const _ = require('lodash');
const areEqual = _.isEqual( {a:1,b:2} , {a:1,b:2} ) ; // returns true

所以你应该可以这样说:

const _ = require('lodash');
const filtered = array1.map( o => {
  return {
    ...o,
    child: _.isEqual( o.child, array2 ) ? [] : o.child ),
  }
});

【讨论】:

    【解决方案2】:

    是的,你可以这样试试。

    array1.map(item1 => ({ ...item1, child: item1.child.filter(childItem => !array2.find(item2 => JSON.stringify(item2) === JSON.stringify(childItem))) }));

    如果对象的键顺序不一样,就像 Everett Glovier 说的,你可以这样尝试。

    array1.map(item1 => ({ ...item1, child: item1.child.filter(childItem => !array2.find(item2 => item2.id === childItem.id && item2.name === childItem.name)) }));

    【讨论】:

    • 请注意:js 键的顺序并不总是相同,所以这可能会返回 false。
    • 无法保证两个看似相同(但不同)的 javascript 对象将序列化为具有相同顺序的属性的 JSON。来自 MDN 关于JSON.stringify() 的文章:“注意: 不保证非数组对象的属性以任何特定顺序进行字符串化。不要依赖字符串化中同一对象内的属性排序。 "
    【解决方案3】:

    您无法在 javascript 中使用包含来比较两个不同的对象,因为包含使用 ===。只有对同一对象的引用才会使用 === 返回 true。您需要编写一个自定义函数,该函数遍历对象的所有键,并在两个数组之间比较它们的值。

    本文介绍了比较两个对象的一些技巧: https://dmitripavlutin.com/how-to-compare-objects-in-javascript/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-08-04
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 2019-02-15
      相关资源
      最近更新 更多