news 2026/10/15 15:32:00

`collapse()`:把数组集合拍平为单一扁平集合

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
`collapse()`:把数组集合拍平为单一扁平集合
  • 开发工具

【免费下载链接】collect.js

💎 Convenient and dependency free wrapper for working with arrays and objects

项目地址:https://gitcode.com/gh_mirrors/co/collect.js
点击查看免费下载

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)); };

整个逻辑只有一行,但包含两个关键点:

  1. [].concat(...this.items):利用数组解构展开(spread)语法把this.items中的每个子数组元素展开,再用concat拼接成一个新数组。这正是 ES6 中实现「扁平化一层」的标准写法。
  2. 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

项目地址:https://gitcode.com/gh_mirrors/co/collect.js
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/15 15:31:54

CF1399C Boats Competition:枚举总重量与计数数组配对解法解析

CF1399C这道题在Codeforces Round #1399 Div. 2 里排在第三题&#xff0c;说难不难&#xff0c;但掉坑的人真不少。题目用一句大白话概括就是&#xff1a;给你一堆选手的体重&#xff0c;让你两两配对去划船&#xff0c;要求每组两个人的体重之和必须完全相等&#xff0c;问最多…

作者头像 李华
网站建设 2026/10/15 15:31:32

SpringBoot时间规划系统毕设模板:可答辩、可复现、防踩坑

简介&#xff1a;本资源是一份面向计算机专业本科生及毕业设计初学者的SpringBoot课程设计论文模板&#xff0c;聚焦时间管理类Web系统开发实践&#xff0c;解决学生在技术选型、架构设计与论文组织上的常见困惑。文档完整覆盖绪论、需求分析、系统设计等标准章节&#xff0c;包…

作者头像 李华
网站建设 2026/10/15 15:30:49

书霸AI实践报告:四个输入项藏着哪些写作细节

写实践报告时&#xff0c;一个容易被忽略的问题是&#xff1a;同样写“参与日常工作”&#xff0c;为什么有人的内容具体&#xff0c;有人的内容却像通用模板&#xff1f;差别往往藏在最初提供的信息里。书霸AI的实践报告页面&#xff0c;把入口收拢为单位、岗位、实践时间和字…

作者头像 李华
网站建设 2026/10/15 15:30:35

无人驾驶MPC控制算法:模型、约束与调参实战解析

简介&#xff1a;这套无人驾驶车辆模型预测控制&#xff08;MPC&#xff09;程序代码&#xff0c;面向学习智能车辆控制的研究者与开发者&#xff0c;解决从理论公式到可运行代码的落地问题。压缩包共16个文件&#xff0c;包含13个MATLAB脚本&#xff08;.m&#xff09;、2个说…

作者头像 李华
网站建设 2026/10/15 15:30:03

基于Swing的扫雷游戏开发:核心算法、英雄榜与避坑实践

简介&#xff1a;包含英雄榜与等级设置的Java扫雷项目源码&#xff0c;面向Java初学者、课程设计及游戏开发入门者&#xff0c;能完整体现经典扫雷玩法。压缩包共19个文件&#xff0c;含7个Java源文件、7个class编译文件、2张GIF图标、英雄榜txt以及Eclipse工程配置&#xff0c…

作者头像 李华