React Native如何实现忽略数组顺序的两个对象相等性校验
React Native 忽略数组元素顺序的对象相等校验方案
你目前使用JSON.stringify对比的问题在于,该方法序列化时会严格遵循数组元素顺序、对象键的输出顺序,只要顺序有差异,序列化结果就会不同,无法满足你的需求。下面提供两种可直接落地的实现方案:
方案1:基于Lodash自定义比较(推荐,边界场景兼容完善)
Lodash的isEqualWith方法支持自定义比较规则,我们可以针对数组类型做忽略顺序的特殊处理:
- 依赖安装(如果项目未引入Lodash,可只安装单包减小体积):
npm install lodash.isequalwith # 或 yarn add lodash.isequalwith
- 比较逻辑实现:
import isEqualWith from 'lodash.isequalwith'; // 可根据业务场景修改数组元素唯一标识的字段名 const ARRAY_ITEM_UNIQUE_KEY = 'addon_id'; const customCompare = (val1, val2) => { // 仅对数组做忽略顺序的特殊处理 if (Array.isArray(val1) && Array.isArray(val2)) { // 数组长度不等直接判定不相等 if (val1.length !== val2.length) return false; // 将第二个数组转为 唯一标识->元素 的映射表 const val2Map = new Map(val2.map(item => [item[ARRAY_ITEM_UNIQUE_KEY], item])); // 遍历第一个数组,逐一匹配元素并深度比较 return val1.every(item => { const matchItem = val2Map.get(item[ARRAY_ITEM_UNIQUE_KEY]); return matchItem ? isEqualWith(item, matchItem, customCompare) : false; }) } // 非数组类型走默认深度比较逻辑 return undefined; } // 调用示例 const isObjEqual = isEqualWith(obj1, obj2, customCompare); console.log(isObjEqual); // 输出 true
方案2:自研轻量比较函数(无第三方依赖)
如果不想引入外部依赖,可直接使用以下轻量实现,适配常规业务场景:
/** * 深度比较两个值是否相等,数组忽略元素顺序 * @param {*} a 比较值1 * @param {*} b 比较值2 * @param {string} arrayItemUniqueKey 数组对象元素的唯一标识字段 * @returns {boolean} 是否相等 */ const deepEqualIgnoreArrayOrder = (a, b, arrayItemUniqueKey = 'addon_id') => { // 基础类型/引用地址相等直接返回true if (a === b) return true; // 空值/类型不同直接返回false if (a == null || b == null || typeof a !== typeof b) return false; // 数组比较逻辑 if (Array.isArray(a) && Array.isArray(b)) { if (a.length !== b.length) return false; const bMap = new Map(b.map(item => [ typeof item === 'object' && item !== null ? item[arrayItemUniqueKey] : item, item ])); return a.every(item => { const key = typeof item === 'object' && item !== null ? item[arrayItemUniqueKey] : item; const match = bMap.get(key); return match ? deepEqualIgnoreArrayOrder(item, match, arrayItemUniqueKey) : false; }) } // 对象比较逻辑 if (typeof a === 'object') { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) return false; return aKeys.every(key => bKeys.includes(key) && deepEqualIgnoreArrayOrder(a[key], b[key], arrayItemUniqueKey)) } return false; } // 调用示例 console.log(deepEqualIgnoreArrayOrder(obj1, obj2)); // 输出 true
注意事项
- 如果数组内元素为基础类型(数字、字符串等),上述逻辑会自动把元素本身作为唯一标识匹配,无需额外修改
- 如果比较的对象存在循环引用,需要额外增加缓存逻辑避免栈溢出,普通业务场景无需处理
内容的提问来源于stack exchange,提问作者carch
相关产品推荐
相关产品推荐

