ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

es-toolkit 兼容版 xorBy 使用指南:按自定义规则计算多数组对称差集

es-toolkit 兼容版 xorBy 使用指南:按自定义规则计算多数组对称差集 es-toolkit 兼容版 xorBy 使用指南按自定义规则计算多数组对称差集【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit本文围绕 es-toolkit 的 Lodash 兼容版xorBy展开讲解如何基于自定义变换规则函数、属性名、部分对象计算多个数组的对称差集并结合仓库源码剖析其内部实现、与原生版xorBy的差异以及性能取舍。读完本文你将掌握xorBy的完整调用方式、iteratee的四种形态以及何时应该改用更快的现代版 API。一、xorBy 是什么兼容层中的对称差集工具xorBy是 es-toolkit 的 Lodash 兼容模块es-toolkit/compat中提供的数组工具函数。它的作用是对多个数组做**对称差集symmetric difference**计算但比较的基准不是元素本身而是每个元素经过变换函数iteratee处理后的结果。所谓对称差集是指「只存在于其中一个集合、但不同时出现在多个集合中」的元素集合。与xor相比xorBy多接受一个变换函数允许你按对象的某个属性、字符串长度、取整结果等任意规则来判定元素是否重复因此在处理对象数组时尤为实用。需要注意的是在 es-toolkit 的兼容文档 中官方明确给出警告兼容版xorBy因需要处理null/undefined、复杂的去重计算逻辑运行速度较慢推荐优先使用更快的现代版 xorByarray 模块。兼容版的定位是为 Lodash 代码平滑迁移提供行为一致性而不是追求极致性能。二、基本用法与完整示例xorBy的调用签名如下const result xorBy(...arrays, iteratee);多个数组依次传入最后一个参数是变换函数iteratee。函数会对每个数组的每个元素应用该变换然后按变换后的结果计算对称差集变换结果恰好只出现在其中一个数组中的元素会被保留在结果中。从es-toolkit/compat导入import { xorBy } from es-toolkit/compat;场景一按 Math.floor 取整结果比较数值// 以 Math.floor 的结果为基准计算对称差集 xorBy([2.1, 1.2], [4.3, 2.4], Math.floor); // 返回: [1.2, 4.3]2.1与2.4取整后都是2属于重复项被剔除1.2floor 为1和4.3floor 为4的变换结果只出现一次因此被保留。场景二按对象属性名比较// 以对象的 x 属性为基准计算对称差集 xorBy([{ x: 1 }], [{ x: 2 }, { x: 1 }], x); // 返回: [{ x: 2 }]这里iteratee直接传入了字符串xes-toolkit 会把它解析为「取对象的x属性」函数。{ x: 1 }在两个数组中同时出现被剔除{ x: 2 }只出现一次被保留。场景三传函数作为变换规则const users1 [{ name: John, age: 30 }]; const users2 [ { name: Jane, age: 25 }, { name: John, age: 30 }, ]; xorBy(users1, users2, user user.name); // 返回: [{ name: Jane, age: 25 }]John同时存在于两个数组被剔除Jane只出现一次保留完整对象。场景四三个数组的对称差集xorBy([1.2, 2.3], [3.4, 4.5], [5.6, 6.7], Math.floor); // 返回: [1.2, 2.3, 3.4, 4.5, 5.6, 6.7]三个数组各元素的取整结果1、2、3、4、5、6互不重复因此全部保留。场景五null / undefined 会被忽略xorBy([2.1, 1.2], null, [4.3, 2.4], Math.floor); // 返回: [1.2, 4.3]null和undefined参数会被静默忽略不会参与计算也不会抛错。这在从 Lodash 迁移、参数可能动态拼接的场景下很安全。参数与返回值参数...arraysArrayArrayLikeT | null | undefined | ValueIterateeT参与对称差集计算的多个数组以及末尾的变换函数。数组可以是类数组对象ArrayLike、null或undefined变换函数可以是函数、属性名、部分对象等详见下文 iteratee 详解。返回值T[]以变换函数的结果为基准只出现在其中一个数组中的元素组成的新数组。三、iteratee 的四种形态从源码看参数解析兼容版xorBy的关键设计在于对iteratee的灵活解析。查看其实现 src/compat/array/xorBy.ts可以看到处理逻辑export function xorByT(...values: ArrayArrayLikeT | null | undefined | ValueIterateeT): T[] { const lastValue last(values); let mapper identity; if (!isArrayLikeObject(lastValue) lastValue ! null) { mapper iteratee(lastValue); values values.slice(0, -1); } // ... }实现首先取出最后一个参数lastValue如果它不是类数组对象isArrayLikeObject为 false且不为null/undefined就把它当作 iteratee 交给iteratee工厂函数 转换成统一格式的映射函数同时将其从数组列表中剔除。也就是说只要最后一个参数是数组或类数组就不会被误当成 iteratee这也解释了为何xorBy([1, 2], [2, 3])不带 iteratee 也能正常工作此时 mapper 退化为恒等函数identity。iteratee工厂函数支持四种输入形态见 src/compat/util/iteratee.ts传入形态解析结果示例函数原样返回该函数iteratee(user user.name)属性名字符串/数字/symbol返回取值函数property(value)iteratee(x)等价于obj obj.x二元数组[key, value]返回匹配属性值的函数matchesPropertyiteratee([x, 1])判断obj.x 1部分对象返回深度匹配函数matchesiteratee({ x: 1 })判断对象是否匹配该子集null/undefined/缺省返回恒等函数identity元素原样参与比较这四种形态意味着兼容版xorBy可以完全复刻 Lodash 的调用习惯既可以用Math.floor这样的函数也可以用x这样的属性名甚至可以传入{ status: active }这样的部分对象做结构化比较。四、底层实现并集、交集与差集的组合运算兼容版的实现思路从 src/compat/array/xorBy.ts 的核心实现可以看到对称差集是通过「并集 - 交集」的组合运算得出的const arrays values.filter(isArrayLikeObject) as [any]; if (arrays.length 2) { return uniq(arrays[0]); } const union unionBy(...arrays, mapper); const intersections windowed(arrays, 2).map(([arr1, arr2]) intersectionBy(arr1, arr2, mapper)) as [any]; return differenceBy(union, unionBy(...intersections, mapper), mapper) as T[];具体步骤用filter(isArrayLikeObject)剔除所有非数组参数null、undefined、数字等仅保留真正的数组/类数组参与计算如果有效数组少于 2 个直接返回uniq去重后的结果与 Lodash 行为一致单数组只做去重计算所有数组的并集unionBy用windowed(arrays, 2)对数组做滑动窗口分组对每两个相邻数组计算交集intersectionBy再把所有交集合并unionBy得到「重复元素集合」最后用differenceBy(union, 重复集合, mapper)从并集中剔除所有重复元素得到对称差集。这种「并集减去重复项」的通用算法可以正确处理任意数量的数组代价是多次全量遍历与去重这正是官方文档警告「复杂重复计算逻辑导致较慢」的根源。现代版的简洁对照作为对比现代版 src/array/xorBy.ts 仅支持两个数组 一个映射函数实现非常直接export function xorByT, U(arr1: readonly T[], arr2: readonly T[], mapper: (item: T) U): T[] { const union unionBy(arr1, arr2, mapper); const intersection intersectionBy(arr1, arr2, mapper); return differenceBy(union, intersection, mapper); }由于现代版不做null/undefined容忍、不支持属性名/部分对象等 iteratee 形态、也不需要处理任意数量数组其内部循环与中间数组更少因此更快、包体积更小。这也是文档推荐优先使用es-toolkit/array版xorBy的原因。两者的性能差异在仓库的基准测试 benchmarks/performance/xorBy.bench.ts 中有直接对比测试同时运行es-toolkit/xorBy、es-toolkit/compat/xorBy与lodash/xorBy并且包含一个各 10000 个对象id从0到9999、5000到14999的大数组场景。如需自行复现可在仓库根目录运行基准测试命令。五、边界行为与测试验证兼容版xorBy的边界行为在 src/compat/array/xorBy.spec.ts 中有完整覆盖值得关注的语义包括1. 单数组返回去重结果xorBy([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]); // [1, 4] xorBy([1, 1]); // [1]单数组只去重 xorBy([1]); // 返回新数组与原数组引用不同2. 非数组参数被忽略const array [1, 2]; xorBy(array, 3, { 0: 1 }, null); // array数字、普通对象、null 均被忽略 xorBy(null, array, null, [2, 3]); // [1, 3]注意普通对象{ 0: 1 }会被忽略但类数组对象如函数的arguments对象会被当作有效数组参与计算——这正是isArrayLikeObject检查的意义。3. 单数组时 iteratee 被忽略与 Lodash 一致xorBy([2.1, 2.3], Math.floor); // [2.1, 2.3]不应用 iteratee xorBy(Math.floor); // []没有数组时返回空数组 xorBy([NaN, NaN], Math.floor); // [NaN] xorBy([-0], Math.floor); // [0]这是一个容易踩坑的细节当只传一个数组时末尾参数即使看起来像函数也不会被当作 iteratee 处理。测试中还验证了-0会被规范化为0、NaN按自身去重等一致性行为。4. 元素去重语义xorBy([1, 1, 2, 5], [2, 2, 3, 5], [3, 4, 5, 5]); // [1, 4]数组内部的重复元素先被合并再参与对称差集计算结果中不会出现重复项。六、应用场景与迁移建议综合来看兼容版xorBy的典型使用场景包括Lodash 迁移已有代码使用lodash.xorBy希望无痛切换到 es-toolkit。由于兼容层刻意保持 Lodash 的调用签名与边界行为支持任意数量数组、null容忍、字符串属性名 iteratee通常只需把 import 路径从lodash改为es-toolkit/compat即可。对象数组按属性比较需要按id、name等属性判定重复但又希望返回完整的原始对象而不是属性值本身。多数组场景三个以上数组需要计算「全局只出现一次」的元素且对null参数有容错需求。而如果你的代码是全新编写、只需要在两个数组间按函数规则计算对称差集官方建议直接使用 es-toolkit/array 的 xorBy它在性能与包体积上更优import { xorBy } from es-toolkit/array; xorBy([{ id: 1 }, { id: 2 }], [{ id: 2 }, { id: 3 }], obj obj.id); // 返回: [{ id: 1 }, { id: 3 }]总结xorBy是 es-toolkit 兼容层中用于按自定义规则计算多数组对称差集的标准工具。它通过iteratee工厂把函数、属性名、属性值对、部分对象统一转换为比较基准通过「并集 - 交集」的组合算法处理任意数量的数组并对null/undefined、非数组参数、单数组去重等边界行为提供了与 Lodash 一致的处理。理解其实现原理与边界语义能帮助你在迁移 Lodash 代码时做出正确的取舍追求行为一致用es-toolkit/compat的xorBy追求性能与体积则选用es-toolkit/array的现代版xorBy。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表