You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用高效函数式编程实现非原始值数组B相对于A的相对补集?

解决对象数组的相对补集问题(B相对于A)

这问题我做项目时也碰到过,确实_.without只支持原始值数组,完全没法处理对象的情况。给你两个高效的函数式解决方案,刚好匹配你的需求:

方案一:用Lodash原生方法_.differenceWith

Lodash其实有专门处理对象数组差异的方法,就是_.differenceWith,它支持传入自定义比较器函数,完美适配这个场景:

const _ = require('lodash');

const arrayA = [{ id: 1 }, { id: 2 }];
const arrayB = [{ id: 2 }, { id: 3 }];

// 用_.isEqual做深度比较,也可以自定义对比逻辑(比如只匹配id)
const relativeComplement = _.differenceWith(arrayB, arrayA, _.isEqual);
console.log(relativeComplement); // 输出: [{ id: 3 }]

如果你的匹配逻辑只需要对比id而非整个对象,还可以写个更轻量的比较器:

const relativeComplement = _.differenceWith(arrayB, arrayA, (a, b) => a.id === b.id);

这个方法是Lodash优化过的,性能比自己手写循环靠谱得多。

方案二:原生JavaScript函数式实现(不依赖Lodash)

如果不想用第三方库,原生JS也能写出高效的函数式代码,核心思路是先把数组A的标识(比如id)存入Set,再过滤数组B:

const arrayA = [{ id: 1 }, { id: 2 }];
const arrayB = [{ id: 2 }, { id: 3 }];

// 第一步:提取A中所有id存入Set,O(n)时间复杂度
const aIds = new Set(arrayA.map(item => item.id));

// 第二步:过滤B中不在A里的元素,O(m)时间复杂度
const relativeComplement = arrayB.filter(item => !aIds.has(item.id));
console.log(relativeComplement); // 输出: [{ id: 3 }]

这个方案的时间复杂度是O(n+m),效率拉满。如果需要对比整个对象而非单个字段,可以把对象转成JSON字符串存入Set(注意要保证对象键顺序一致,否则会被判定为不同):

const aItemStrs = new Set(arrayA.map(item => JSON.stringify(item)));
const relativeComplement = arrayB.filter(item => !aItemStrs.has(JSON.stringify(item)));

要是担心键顺序的问题,也可以结合深度比较函数过滤(但这种方式时间复杂度是O(n*m),数组较大时不推荐):

const relativeComplement = arrayB.filter(bItem => !arrayA.some(aItem => _.isEqual(aItem, bItem)));

总结

  • 已经在用Lodash的话,优先用_.differenceWith,简洁又高效
  • 原生场景下,Set+filter的方案性能最优,完全符合函数式编程的风格

内容的提问来源于stack exchange,提问作者LiranC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:17:33