ARTICLE DETAIL

资讯详情

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

es-toolkit 迭代器版 cartesianProduct 全解析:惰性计算笛卡尔积的用法、原理与资源管理

es-toolkit 迭代器版 cartesianProduct 全解析:惰性计算笛卡尔积的用法、原理与资源管理 es-toolkit 迭代器版 cartesianProduct 全解析惰性计算笛卡尔积的用法、原理与资源管理【免费下载链接】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-toolkitcartesianProduct迭代器版是 es-toolkit 在es-toolkit/iterator子路径下提供的笛卡尔积计算函数它以**惰性lazy**方式遍历多个源迭代器按字典序逐一产出所有可能的元组组合。本文将以 docs/ja/iterator/reference/cartesianProduct.md对应英文版 docs/iterator/reference/cartesianProduct.md为骨架结合 src/iterator/cartesianProduct.ts 的源码实现与 src/iterator/cartesianProduct.spec.ts 的测试用例深入讲解它的调用方式、运行机制、边界行为、资源释放语义以及与函数式pipe组合的用法。读完本文你将掌握如何在用户 × 角色配对、参数化测试用例生成、多维组合枚举等场景中正确、高效地使用该 API并理解它为何能支持无限迭代器。快速上手一行为你生成全部组合import { cartesianProduct } from es-toolkit/iterator; const pairs cartesianProduct(source1, source2);把任意数量的源迭代器传入cartesianProduct它会返回一个惰性迭代器每次next()时才计算下一个元组。最典型的使用场景是把所有用户与所有角色一一配对或是从多组参数集合中枚举全部测试用例。import { cartesianProduct, range } from es-toolkit/iterator; // 将第一个源的每个元素与第二个源的每个元素配对。 cartesianProduct([1, 2].values(), [a, b].values()).toArray(); // 返回: [[1, a], [1, b], [2, a], [2, b]] // 最右侧的源推进最快。 cartesianProduct([0, 1].values(), [0, 1].values(), [0, 1].values()).toArray(); // 返回: [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]] // 第一个源可以是无限的元组按需产出。 cartesianProduct(range(0, Infinity), [a, b].values()).take(3).toArray(); // 返回: [[0, a], [0, b], [1, a]]参数与返回值参数sourcesArrayIteratorunknown要求取笛卡尔积的迭代器按可变参数依次传入。这些必须是实现了迭代器协议含next方法的对象例如array.values()、生成器或 es-toolkit 迭代器子路径下的其他惰性迭代器如range。返回值IteratorObject[...], undefined一个惰性迭代器逐条产出表示笛卡尔积的元组元组的具体类型由各源迭代器的元素类型推导得出。它继承了原生Iterator.prototype因此自带map、take、toArray等全部原生迭代器辅助方法可以直接继续链式调用。惰性 缓冲为什么第一个源可以无限理解cartesianProduct的关键在于它对待第一个源与其余源的策略完全不同。这在文档中被明确说明也在源码中得到了印证除第一个源之外的所有源都会在迭代开始时被完整缓冲buffer为数组。因为从算法上看这些源会被反复遍历多次每产生一个第一源元素就要完整扫一遍后面的源不可能在每次需要时重新从头迭代所以一次性物化是最直接的方案。第一个源则是逐个元素惰性消费的因此它可以是无限迭代器——只要你不把结果全部拉完它就不会耗尽。看 src/iterator/cartesianProduct.ts 中的初始化逻辑当第一次请求元素时函数会从下标1开始把sources[1]到最后一个源逐一next()到结束并压入pools数组随后才从sources[0]取出第一个元素作为firstValue。也就是说在真正请求第一个结果之前任何源都不会被触碰对应测试 src/iterator/cartesianProduct.spec.ts 中惰性初始化的断言。其后的每次next()都遵循里程表odometer式的推进逻辑src/iterator/cartesianProduct.ts维护一个与缓冲源数量等长的indices索引数组每次从最右端开始递增发生进位时向左传播并清零当所有缓冲索引都归零回到起点后再从第一个源拉取下一个元素。这正是文档所说最右侧的源推进最快如同里程表的数字的底层实现。与数组版 cartesianProduct 的关系es-toolkit 的数组版cartesianProduct源码见 src/array/cartesianProduct.ts会一次性计算并返回完整的T[][]结果数组迭代器版则把同样的最右侧推进最快、字典序输出语义搬到了惰性迭代器上让用户可以只取前几个结果、组合无限序列或者把结果继续交给map、filter等原生辅助方法做流式处理。两者的边界行为也保持一致不传任何源时只产出一个空元组[]只要任一源为空则什么都不产出src/iterator/cartesianProduct.ts。边界行为与资源释放文档 测试双重印证文档对边界情况给出了明确约定而 src/iterator/cartesianProduct.spec.ts 用 9 组测试逐一锁定了这些行为场景行为对应测试不传任何源只产出一个空元组[[]]src/iterator/cartesianProduct.spec.ts任一源为空不产出任何元组src/iterator/cartesianProduct.spec.ts只有一个源产出单元素元组[x]src/iterator/cartesianProduct.spec.ts第一个源为无限迭代器可按需取前 N 个元组src/iterator/cartesianProduct.spec.ts请求第一个元素之前不触碰任何源纯惰性src/iterator/cartesianProduct.spec.ts消费完毕后再迭代单次可用single-shot返回空src/iterator/cartesianProduct.spec.ts更值得注意的是资源关闭IteratorClose语义。文档明确承诺无论迭代因何种原因结束——第一个源耗尽、某个缓冲源为空、还是消费方提前停止例如take(1)后中断——所有源都会通过其return方法被关闭。这一承诺由 src/iterator/_internal/iterator.ts 中的内部iterator辅助函数兑现它把用户传入的onClose回调包装进符合原生迭代器协议的next/return中保证关闭回调恰好执行一次且关闭后不再调用next。测试 src/iterator/cartesianProduct.spec.ts 分别验证了正常耗尽源为空消费方提前停止三种退出路径下生成器源的finally块都能被触发底层资源文件句柄、网络连接等得以释放。顺带一提内部iterator辅助函数采用手写next闭包 Object.create(Iterator.prototype)的方式而非生成器函数据其注释说明这是刻意的性能取舍直接驱动迭代器协议比yield生成器快约两倍而原型挂载几乎没有额外开销src/iterator/_internal/iterator.ts。与pipe组合es-toolkit/fp/iterator的柯里化形态在函数式组合场景中可以从es-toolkit/fp/iterator导入柯里化版本配合pipe使用。柯里化形态接收一个其他迭代器返回一个函数把管道中传入的迭代器的每个元素与该迭代器的每个元素配对——且其他迭代器一侧推进最快import { pipe } from es-toolkit/fp; import { cartesianProduct, toArray } from es-toolkit/fp/iterator; pipe([1, 2].values(), cartesianProduct([a, b].values()), toArray()); // 返回: [[1, a], [1, b], [2, a], [2, b]]从实现看src/fp/iterator/cartesianProduct.ts它只是把传入的other迭代器与管道传入的source迭代器重新组合后转交给基础版cartesianProductIterator(source, other)语义与直接调用完全一致——other会被缓冲为数组source惰性消费、可为无限。相关导出位于 src/fp/iterator/index.ts同时es-toolkit/fp/iterator下还提供了map、filter、take、toArray等配套的柯里化辅助函数便于在pipe中完成生成组合 → 过滤 → 截断 → 物化的整条流水线。实用建议与注意点综合文档、源码与测试使用cartesianProduct迭代器版时有几点值得注意把可能无限的迭代器放在第一个参数位置其余源放到后面后面的源会被完整缓冲因此应尽量传入规模有限的序列避免无谓的内存占用。产出总量是各源长度的乘积即使惰性计算toArray()全部物化时仍可能指数级膨胀配合take(n)只取所需部分是发挥其惰性价值的最佳姿势。结果迭代器是单次可用的消费完毕后再次迭代将得到空结果如需多轮使用请重新构造或自行缓冲。资源释放是自动的无论正常结束还是提前中断所有源都会被调用return()关闭因此可以放心把生成器、文件流等带清理逻辑的迭代器传进去。需要一次性拿到全部结果、且输入本身是数组时直接使用数组版cartesianProduct即可它会预分配结果数组一次性返回免去迭代器协议的开销。如需查看完整的迭代器工具集range、zip、chunk、scan等可参考 docs/iterator/reference 目录与 src/iterator/index.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),仅供参考
返回列表