如何使用Lodash比较两个索引无关的对象数组是否匹配?
使用Lodash验证无序对象数组的元素匹配
刚好我之前也遇到过类似的场景,用Lodash可以很简洁地解决这个问题,完全不用折腾排序或者手动映射。核心是利用Lodash的深度比较和数组遍历方法,来确认两个数组的元素是完全匹配的(不考虑顺序)。
先直接上可行的代码:
const _ = require('lodash'); const arr1 = [{a:'first', b:'second'}, {c:'third', d: 'fourth'}, {e:'fifth', f: 'sixth'}]; const arr2 = [{c:'third', d: 'fourth'}, {e:'fifth', f: 'sixth'}, {a:'first', b:'second'}]; // 验证两个数组元素完全匹配(无序) const arraysAreMatching = arr1.length === arr2.length && _.every(arr1, obj => _.some(arr2, otherObj => _.isEqual(obj, otherObj))); console.log(arraysAreMatching); // 输出 true
代码细节解释:
- 先判断数组长度:这是个快速校验,如果两个数组长度不一样,直接就能确定不匹配,避免后续不必要的遍历,提升整体效率。
_.isEqual(obj, otherObj):这是实现匹配的关键,Lodash的这个方法会深度比较两个对象——不管对象属性的定义顺序,只要键值对完全一致就会返回true。原生JS的===做不到这一点,因为对象是引用类型,即使内容完全相同也会判定为不等。_.some(arr, predicate):用来检查目标数组中是否存在至少一个和当前对象匹配的元素,相当于帮我们问一句“有没有一个对象和我完全一样?”。_.every(arr, predicate):确保原数组中的每一个对象都能在目标数组中找到匹配项,也就是保证arr1里没有任何一个元素是arr2里没有的。
如果你的场景需要考虑“其中一个数组是另一个的子集”(比如arr2比arr1多元素,但arr1的元素都在arr2里),那可以去掉长度判断,同时做双向验证:
const arr1IsSubsetOfArr2 = _.every(arr1, obj => _.some(arr2, otherObj => _.isEqual(obj, otherObj))); const arr2IsSubsetOfArr1 = _.every(arr2, obj => _.some(arr1, otherObj => _.isEqual(obj, otherObj))); const arraysMatchExactly = arr1IsSubsetOfArr2 && arr2IsSubsetOfArr1;
为什么不推荐sort+map方案?
你提到的原生JS sort+map方案确实能解决简单场景,但有几个明显的坑:
- 如果对象的属性顺序不固定(比如后端返回的对象属性顺序偶尔变化),转成字符串后会被判定为不等,但实际内容却是一致的。
- 如果对象存在嵌套结构(比如
{a: {b: 1}}),手动排序属性再转字符串的逻辑会变得非常复杂,很容易出错。 - Lodash的
_.isEqual已经封装了所有深度比较的细节,比自己手写的代码更可靠、更简洁。
内容的提问来源于stack exchange,提问作者Glendon Philipp Baculio
相关产品推荐
相关产品推荐

