ARTICLE DETAIL

资讯详情

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

es-toolkit/fp 中的 differenceBy:函数式管道中的按映射键差集操作

es-toolkit/fp 中的 differenceBy:函数式管道中的按映射键差集操作 es-toolkit/fp 中的 differenceBy函数式管道中的按映射键差集操作【免费下载链接】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/fp是 es-toolkit 的函数式编程入口它把differenceBy等数组操作改写为data-last数据最后传入的形态使其可以直接嵌入pipe管道用自上而下的顺序表达数据变换。本文将围绕 docs/fp/reference/differenceBy.md 展开讲解 fp 版differenceBy的用法、参数语义、返回值并结合仓库源码剖析其基于Set的去重实现与pipe中的惰性求值lazy evaluation机制帮助你在实际项目中写出可读、高效且可提前终止的管道式差集代码。一、fp 版 differenceBy 是什么differenceBy函数式变体会创建一个按映射键排除值的函数通常与pipe搭配使用const result pipe(array, differenceBy(secondArray, mapper));它与 es-toolkit 原始版differenceBy的区别在于调用形态原始版data-firstdifferenceBy(firstArr, secondArr, mapper)三个参数一次性传入返回结果数组fp 版data-lastdifferenceBy(secondArray, mapper)只传入配置要排除的数组和映射函数返回一个等待数据的函数(array) T[]由pipe把数据喂给它。正如文档中的提示所述在普通代码中应优先使用原始版differenceBy只有当你需要与pipe组合表达变换流水线时才使用这个 fp 变体。二、用法按映射键计算差集differenceBy会比较mapper返回的值来自管道数组piped array的元素只要其映射键没有出现在secondArray中就会被保留。import { differenceBy, pipe } from es-toolkit/fp; pipe( [{ id: 1 }, { id: 2 }], differenceBy([2], value (typeof value number ? value : value.id)) ); // [{ id: 1 }]这个例子里mapper对两种类型的元素做了归一化数字2映射为自身2对象{ id: 2 }映射为2。映射后两者的键相同因此{ id: 2 }被排除只留下{ id: 1 }。这正是基于特定标准计算差集的典型用法——两个数组的元素类型可以不同只要映射后的键可比即可。参数参数类型说明secondArrayreadonly U[]包含应被排除元素按映射键的数组mapper(item: T \| U) unknown返回比较键的函数同时作用于两个数组的元素返回值(array: readonly T[]) T[]—— 一个函数将readonly T[]映射为键未出现在secondArray中的元素数组。三、源码剖析data-last 签名与 Set 映射fp 版differenceBy的完整实现在 src/fp/array/differenceBy.ts核心签名如下export function differenceByT, U( secondArray: readonly U[], mapper: (value: T | U) unknown ): (array: readonly T[]) T[] { const mappedSecondSet new Set(secondArray.map(item mapper(item))); function differenceByEager(array: readonly T[]): T[] { return differenceByToolkit(array, secondArray, mapper); } const differenceByLazy createLazyFunctionT, T((value, _index, emit) { if (!mappedSecondSet.has(mapper(value))) { emit(value); } }); return combineEagerAndLazyFunctions(differenceByEager, differenceByLazy); }这里可以观察到三个关键设计闭包捕获配置数据后置调用differenceBy(secondArray, mapper)时立即用new Set(secondArray.map(item mapper(item)))预计算排除键集合详见 src/fp/array/differenceBy.ts返回的函数只负责接收数组并做过滤判断。由于Set查找是 O(1)整个过滤过程对每个元素只需一次映射加一次哈希查找。eager 实现直接复用原始版differenceByEager内部调用differenceByToolkit(array, secondArray, mapper)即 src/array/differenceBy.ts 中的原始>const groups chunkFunctions(functions); if (group.lazy isIterable(output) (group.shortCircuit || !Array.isArray(output))) { output lazyPipe(output, group); }lazyPipesrc/fp/pipe.ts从最后一个函数开始倒序组合各 lazy 变换然后用单层循环逐元素驱动整条管道不再为每一步构建中间数组。当尾部存在take这类shortCircuit函数时某个emit返回false会立刻中断驱动循环src/fp/pipe.ts剩余输入永远不会被访问。对differenceBy而言这意味着你可以写出这样的高效管道import { pipe, differenceBy, take } from es-toolkit/fp; // 只要收集到 2 个结果就停止遍历大数组的大部分元素根本不会被处理 pipe( hugeArray, differenceBy([blockedKey1, blockedKey2], item item.id), take(2) );由代码结构可以推断differenceBy的 lazy 形态与take等短路函数相邻时pipe会融合它们并提前终止而单独调用或与普通函数混排时则走differenceByEager的原生数组路径性能与filter相当没有任何额外开销。五、测试验证与边界行为仓库中的测试 src/array/differenceBy.spec.ts 验证了核心语义基础映射差集differenceBy([1.2, 2.3, 3.4], [1.2], Math.floor)返回[2.3, 3.4]——1.2与1.2经Math.floor都映射为1故被排除空数组输入返回空数组。异构类型比较CSV[]与JSON[]两种不同结构仅id相同的数组通过value value.id映射后正确排除id相同的元素。这两个用例说明了differenceBy的两个实用边界比较键是映射结果而非元素本身因此1.2 与 1.2 按Math.floor视为相同这类场景必须用differenceBy而非difference两个数组类型可以不同T ≠ U只要mapper能把两边归一化到同一键空间。六、何时用 fp 版 differenceBy结合 docs/fp/intro.md 的定位建议按如下原则取舍需要表达自上而下的变换流水线如pipe(array, differenceBy(blocked, k k.id), take(n))时使用 fp 版可读性与融合效率兼得只需要一次性计算两个数组的差集时直接使用differenceBydata-first 形态调用更简洁从 lodash 迁移、需要保持 lodash 调用风格的项目可参考es-toolkit/compat入口。总结fp 版differenceBy是 es-toolkit/fp 中配置先行、数据后至设计的典型代表它预计算排除键集合、复用原始版核心实现并通过combineEagerAndLazyFunctions同时具备 eager 与 lazy 两种执行形态。放入pipe后它可以与相邻惰性函数融合为单次遍历并支持提前终止让你以自上而下的可读代码获得接近手写循环的效率。理解其实现src/fp/array/differenceBy.ts、src/fp/_internal/lazy.ts、src/fp/pipe.ts后你可以更有把握地在实际项目中编排差集过滤管道。【免费下载链接】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),仅供参考
返回列表