如何判断对象数组间是否存在全属性匹配的公共元素并求交集?
判断两个对象数组的全属性匹配交集并获取结果
如何判断两个对象数组是否存在全属性匹配的公共元素,并获取这些交集元素?例如下面示例中,数组1里ProductId为3的对象和数组2中的对应对象完全一致。目前用双重for循环可以实现,但想知道有没有更高效的ES语法或Lodash工具函数可用。
示例代码(原双重循环思路)
array1.forEach(arr1 => { array2.forEach(arr2 => { if (arr1.productId === arr2.productId && arr1.productName === arr2.productName ... }) })
对象数组1
[ { ProductId: 50, ProductName: 'Test1', Location: 77, Supplier: 11, Quantity: 33 }, { ProductId: 3, ProductName: 'GHI', Location: 1, Supplier: 4, Quantity: 25 } ]
对象数组2
[ { ProductId: 1, ProductName: 'ABC', Location: 3, Supplier: 4, Quantity: 52 }, { ProductId: 2, ProductName: 'DEF', Location: 1, Supplier: 2, Quantity: 87 }, { ProductId: 3, ProductName: 'GHI', Location: 1, Supplier: 4, Quantity: 25 }, { ProductId: 4, ProductName: 'XYZ', Location: 5, Supplier: 6, Quantity: 17 } ]
一、原生ES实现方案
1. JSON.stringify快速匹配(适合简单对象)
把数组2的对象转为字符串存入Set,遍历数组1时通过字符串匹配快速判断是否存在,时间复杂度O(n+m),比双重循环高效得多。
// 预存数组2的字符串化对象 const array2StrSet = new Set(array2.map(item => JSON.stringify(item))); // 筛选交集 const intersection = array1.filter(item => array2StrSet.has(JSON.stringify(item))); console.log(intersection); // 输出:[{ ProductId: 3, ProductName: 'GHI', Location: 1, Supplier: 4, Quantity: 25 }]
⚠️ 注意:仅适用于属性顺序固定、无函数/undefined等JSON不可序列化类型的对象,因为JSON.stringify的结果会受属性顺序影响。
2. 自定义深度比较(适合复杂场景)
如果对象属性顺序可能变化或包含嵌套对象,需要自定义全属性比较函数,结合filter和some实现:
// 自定义深度比较函数 function isEqual(obj1, obj2) { const keys1 = Object.keys(obj1); const keys2 = Object.keys(obj2); // 属性数量不同直接不匹配 if (keys1.length !== keys2.length) return false; // 遍历所有属性值 for (const key of keys1) { const val1 = obj1[key]; const val2 = obj2[key]; // 基础类型不相等则返回false if (val1 !== val2) { // 嵌套对象递归比较 if (typeof val1 === 'object' && typeof val2 === 'object') { if (!isEqual(val1, val2)) return false; } else { return false; } } } return true; } // 获取交集 const intersection = array1.filter(item1 => array2.some(item2 => isEqual(item1, item2)));
这种方法更灵活,但时间复杂度仍为O(n*m)。如果数组较大,可以先通过唯一标识(如ProductId)预分组,减少后续比较次数。
二、Lodash工具函数实现
Lodash的_.intersectionWith配合_.isEqual可以直接解决问题,代码简洁且支持复杂对象的深度比较:
const _ = require('lodash'); const intersection = _.intersectionWith(array1, array2, _.isEqual);
_.isEqual会忽略属性顺序,支持嵌套对象、数组等复杂类型,是最省心的方案,推荐在已有Lodash依赖的项目中使用。
方案对比
- JSON.stringify法:速度最快,但局限性强,仅适合简单、属性顺序固定的对象。
- 自定义深度比较:灵活度高,但效率一般,适合需要自定义比较逻辑的场景。
- Lodash法:简洁可靠,支持复杂对象,优先推荐。
内容的提问来源于stack exchange,提问作者mattsmith5
相关产品推荐
相关产品推荐

