- 开发工具
【免费下载链接】collect.js
💎 Convenient and dependency free wrapper for working with arrays and objects
collapse()是 collect.js 提供的一个极简且实用的方法,它把「由多个数组组成的集合」拍平成一个单一的扁平集合。无论是处理分页数据、批量结果,还是把多行分组数据合并成一条统一列表,collapse()都能一行代码完成降维。读完本文,你将掌握collapse()的调用方式、底层实现原理、与flatten()/map()/chunk()等方法的配合技巧,以及它的边界行为与适用场景。
基本用法:一行代码拍平集合
collapse()接收一个由数组组成的集合,返回一个新的扁平集合。它的用法非常直接:
const collection = collect([[1], [{}, 5, {}], ['xoxo']]); const collapsed = collection.collapse(); collapsed.all(); // [1, {}, 5, {}, 'xoxo']注意输出结果:原来的三个数组[1]、[{}, 5, {}]、['xoxo']被合并为一个数组,元素顺序保持不变。{}这样的对象元素会被原样保留,不会被进一步展开——这是collapse()与flatten()的关键区别之一(见下文对比)。
再看一个更纯粹的数值例子:
const collection = collect([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); const collapsed = collection.collapse(); collapsed.all(); // [1, 2, 3, 4, 5, 6, 7, 8, 9]collapse()只展开一层数组结构,相当于把所有子数组元素依次拼接在一起。它不会递归展开嵌套更深的数组,这一点与flatten()不同。
在 TypeScript 中的类型签名
collect.js 自带完整的类型声明(index.d.ts),collapse()的签名如下:
collapse(): Collection<Item>;也就是说,对Collection<Item[]>调用collapse()后返回Collection<Item>,类型层面也体现了「把元素类型降低一维」的语义:
import collect from 'collect.js'; const groups = collect([[1, 2, 3], [4, 5, 6]]); const flat: typeof groups = groups.collapse(); // Collection<number>底层实现:只有一行的核心逻辑
collapse()的实现是整个 collect.js 中极简的实现之一,完整源码位于 src/methods/collapse.js:
'use strict'; module.exports = function collapse() { return new this.constructor([].concat(...this.items)); };整个逻辑只有一行,但包含两个关键点:
[].concat(...this.items):利用数组解构展开(spread)语法把this.items中的每个子数组元素展开,再用concat拼接成一个新数组。这正是 ES6 中实现「扁平化一层」的标准写法。new this.constructor(...):通过this.constructor构造一个新的 Collection 实例,而不是修改原集合。这保证了 collect.js 的方法链(method chaining)语义——collapse()返回的是全新的集合,原集合不受影响。
在 src/index.js 中,该方法通过以下方式挂载到原型上:
Collection.prototype.collapse = require('./methods/collapse');所以在运行时,collapse()与其他约 90 个方法一样,可以在链式调用中无缝衔接。
为什么是this.constructor而不是Collection?
使用this.constructor而不是硬编码的Collection,是 collect.js 的一贯做法。这样当用户通过collect(collection)或new Collection(items)创建实例时,collapse()返回的实例类型始终与调用者一致,即使是通过macro()扩展的自定义子类也能保持正确的类型。从源码结构看,这是 collect.js 全库统一的设计约定,保证方法链的返回类型不丢失。
测试验证:行为与预期完全一致
collect.js 的每个方法都配有对应的单元测试,collapse()的测试位于 test/methods/collapse_test.js:
'use strict'; module.exports = (it, expect, collect) => { it('should collapse a collection of arrays into a flat collection', () => { const collection = collect([[1], [{ name: 'Daniel' }, 5], ['xoxo']]); const collapsed = collection.collapse(); expect(collapsed.all()).to.eql([1, { name: 'Daniel' }, 5, 'xoxo']); }); };测试用例验证了两个重要行为:
- 对象元素原样保留:
{ name: 'Daniel' }在 collapse 后没有被拆散,仍然作为整体元素存在; - 顺序保持:展开后的元素顺序严格按照子数组的出现顺序排列。
运行整个测试套件的方式是:
npm test(collect.js 使用 mocha 作为测试框架,测试入口为 test/tests.js,运行前会自动通过 babel 转译src目录。)
与flatten()的区别:一层 vs 递归
collapse()与 flatten() 经常被拿来比较,它们都能把多维结构变平,但语义完全不同:
| 方法 | 展开层级 | 对象处理 | 适用场景 |
|---|---|---|---|
collapse() | 只展开一层数组 | 对象原样保留 | 合并多个数组/分页结果 |
flatten() | 默认递归到无限深,可传depth限制 | 对象属性会被拆开摊平 | 彻底压平任意嵌套结构 |
看flatten()的示例就能直观感受差异:
const collection = collect({ club: 'Liverpool', players: ['Salah', 'Firmino', 'Núñez'], }); const flattened = collection.flatten(); flattened.all(); // ['Liverpool', 'Salah', 'Firmino', 'Núñez'];flatten()会把对象属性值也摊平;而collapse()遇到{}只会把它当作一个普通元素保留。从 src/methods/flatten.js 的实现看,flatten(depth)默认depth = Infinity,会循环调用内部flat函数直到集合中不再存在对象为止。而 src/methods/collapse.js 只做一次[].concat(...)展开。
结论:如果你的数据是「数组的数组」(如分页数据、按组分好批的结果),用collapse();如果你需要把任意嵌套的对象/数组彻底压平成纯值列表,用flatten()。
实战组合:collapse 与链式方法配合
collapse()的价值在链式调用中体现得最充分。以下是几个常见组合。
与map()配合:把分组结果合并为统一列表
const orders = collect([ { id: 1, items: ['apple', 'banana'] }, { id: 2, items: ['orange'] }, ]); const allItems = orders.map(order => order.items).collapse(); allItems.all(); // ['apple', 'banana', 'orange']先用map()提取每个订单的items数组,再用collapse()合并成一个扁平列表——这是处理「一对多关系聚合」的经典写法。
与chunk()配合:先分组再合并
chunk() 把集合按固定大小切块,collapse()可以把切块后的结果重新合并:
const collection = collect([1, 2, 3, 4, 5, 6, 7]); const chunks = collection.chunk(4); chunks.all(); // [[1, 2, 3, 4], [5, 6, 7]] const back = chunks.collapse(); back.all(); // [1, 2, 3, 4, 5, 6, 7]注意chunk()返回的是Collection<Collection>的集合(chunk 的每个元素是子 Collection,见 src/methods/chunk.js),collapse()会把这些子 Collection 当作元素展开。从 src/index.js 的构造函数可以看出,当传入的元素是 Collection 实例时,this.items会保存其内部数组,因此collapse()依然能正确拼接。
与filter()配合:先过滤再合并
const collection = collect([ ['a', 'b'], [], ['c'], ]); const result = collection.filter(group => group.length > 0).collapse(); result.all(); // ['a', 'b', 'c']先过滤掉空数组,再collapse()合并,避免把空数组摊进结果。
与unique()配合:合并后去重
const collection = collect([ [1, 2, 3], [3, 4, 5], ]); const unique = collection.collapse().unique(); unique.all(); // [1, 2, 3, 4, 5]collapse()展开后调用 unique() 即可轻松去重。
与pipe()配合:将结果交给后续处理
pipe() 可以把集合直接传给回调函数,适合在链式调用尾部做收尾处理:
const total = collect([[1, 2], [3, 4]]) .collapse() .pipe(items => items.sum()); // 10边界行为与注意事项
空数组会被自然吸收
const collection = collect([[], [1, 2]]); collection.collapse().all(); // [1, 2]空数组展开后不产生任何元素,无需特殊处理。
非数组元素会被原样保留
如果某个元素本身不是数组,collapse()会把它当作普通元素保留在结果中:
const collection = collect([1, [2, 3]]); collection.collapse().all(); // [1, 2, 3]这得益于 spread 语法的行为:[].concat(1, [2, 3])中的1会被直接加入,[2, 3]会被展开。不过要注意,collect.js 官方文档与测试均以「数组的集合」为标准输入,混合类型输入时建议先用filter()等方法统一数据结构。
不做递归展开
collapse()只展开一层。对于[[[1, 2]]]这样的结构:
const collection = collect([[[1, 2]]]); collection.collapse().all(); // [[1, 2]]结果中仍是一个嵌套数组。需要多级展开时,请使用flatten()并配合depth参数控制层级(详见 flatten() 文档)。
不修改原集合
collapse()返回新集合,原集合保持不变。这与其他所有 collect.js 方法保持一致,便于在链式调用中多次复用同一个原始集合。
典型应用场景小结
- 分页数据合并:把多页接口返回的数组
[[page1], [page2], [page3]]合并为一条完整列表; - 批量结果聚合:把多个查询/计算结果的数组拼接为统一数据集;
- 多字段列表合并:把对象中多个数组属性先
map()出来再collapse()成单一列表; - 配合分组/切片:与
chunk()、split()(src/methods/split.js)等产生嵌套集合的方法配合,快速还原扁平结构。
参考
- 方法文档:docs/api/collapse.md
- 源码实现:src/methods/collapse.js
- 单元测试:test/methods/collapse_test.js
- 类型声明:index.d.ts(
collapse(): Collection<Item>;) - 方法注册:src/index.js
- 相关方法:flatten()、chunk()、unique()、pipe()、map()
- 开发工具
【免费下载链接】collect.js
💎 Convenient and dependency free wrapper for working with arrays and objects
相关推荐
H2O LLM Studio 数据集合并指南:将训练集与验证集合并为单一数据集
H2O LLM Studio 数据集合并指南:将训练集与验证集合并为单一数据集 本文围绕 H2O LLM Studio 的 Merge datasets(合并数
微调大模型AI 应用RxJS v4 `mergeAll` 运算符完全解析:将高阶 Observable 扁平合并为单一序列
RxJS v4 mergeAll 运算符完全解析:将高阶 Observable 扁平合并为单一序列 mergeAll (旧名 mergeObservable )
后端Vega Nest Transform 详解:用字段分组把扁平数据转换为树形结构
Vega Nest Transform 详解:用字段分组把扁平数据转换为树形结构 导读 nest 是 Vega 中用于构建层次结构(树)数据的核心变换:它接收一
数据可视化
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考