)
教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载数组分区partitioning在数据处理场景中非常常见它把一组元素按照某个判定条件拆分成两个甚至多个子数组便于后续按组统计、分组渲染或分桶处理。从概念上看把一个数组一分为二与过滤filtering非常相似区别在于过滤会直接剔除不满足条件的元素而分区则保留全部元素只是根据判定函数返回值的真值性truthiness将它们归入不同的组。当分区数量超过两个时思路大致相同但实现上会更微妙一些。本文以 30 seconds of code 仓库中的 partition-array.md 为骨架结合 bifurcate-array.md、group-array-elements.md 等同系列片段与仓库结构讲解双分区与多分区的完整实现、底层原理及工程化取舍。前置知识真值truthy与假值falsy分区实现依赖 JavaScript 的类型强制转换type coercion机制判定函数fn的返回值会被隐式转换为布尔值从而决定元素进入哪个分区。JavaScript 中共有 6 个假值falsy关键字false原始值undefined原始值null空字符串、全局属性NaN表示0的数字或 BigInt0、-0、0.0、-0.0、0n其余所有值都是真值truthy包括看起来像是空的[]与{}。要显式检查真值性可以用Boolean()函数或双取反!!。这一点在partition中体现为fn(val, i, arr) ? 0 : 1中的三元判断完全依赖真值性任何类布尔的返回值如对象、非零数字都会被自动转换。相关内容可参考仓库中的 truthy-falsy-values.md。将数组一分为二基于reduce的经典写法双分区two-partition是最简单的情形只需很少的代码。核心思路是用Array.prototype.reduce()创建一个包含两个子数组的数组作为累加器调用传入的判定函数fn再通过Array.prototype.push()将fn返回true的元素加入第一个数组返回false的加入第二个数组。const partition (arr, fn) arr.reduce( (acc, val, i, arr) { acc[fn(val, i, arr) ? 0 : 1].push(val); return acc; }, [[], []] ); const users [ { user: barney, age: 36, active: false }, { user: fred, age: 40, active: true }, ]; partition(users, o o.active); // [ // [{ user: fred, age: 40, active: true }], // [{ user: barney, age: 36, active: false }] // ]对这段代码逐层拆解累加器初始化[[], []]是一个二维数组索引0存放满足条件的元素索引1存放不满足条件的元素回调参数reduce的回调接收(acc, val, i, arr)四个参数——累加器、当前值、当前索引、原数组这些参数会原样透传给判定函数fn(val, i, arr)因此fn可以基于元素本身、其索引乃至整个数组做出判断分组与写回acc[fn(...) ? 0 : 1].push(val)先计算判定结果再选择目标子数组最后把元素推入回调必须显式return acc这是reduce累加器链式传递的关键不改变原数组整个操作只产生新的嵌套数组原数组保持不变符合不可变immutability风格便于链式组合与函数式编程。值得注意的是这里用三元运算符? 0 : 1把布尔结果映射为数组索引而仓库中的同族片段 bifurcate-array.md 提供了另一个视角bifurcate用预知的布尔值数组替代判定函数filter[i] ? 0 : 1bifurcateBy则用函数判定。两者结构与partition完全同构区别仅在于分组依据的提供方式可见双分区是该仓库中一套高度统一的模式。将数组分为多组reduce结合Map的动态分组把数组分区为任意数量的子数组时挑战略大。依然可以使用Array.prototype.reduce()但累加器不能再是固定的二维数组而要改用Map对象——它以判定函数fn的返回值为键、以子数组为值从而支持任意多个分区。具体而言用Map.prototype.has()检查某个分区是否已存在若已存在用Map.prototype.get()取出该分区的数组并push()新元素若不存在用Map.prototype.set()以[val]创建新分区最后用Map.prototype.values()取得所有分区值的迭代器配合展开运算符...一次性转换为数组。const partitionBy (arr, fn) [ ...arr .reduce((acc, val, i, arr) { const current fn(val, i, arr); if (acc.has(current)) acc.get(current).push(val); else acc.set(current, [val]); return acc; }, new Map()) .values(), ]; const numbers [1, 1, 3, 3, 4, 5, 5, 5]; partitionBy(numbers, n n % 3); // [[1, 1, 4], [3, 3], [5, 5, 5]] partitionBy(numbers, n n); // [[1, 1], [3, 3], [4], [5, 5, 5]]这段实现有三个关键设计点值得展开键的选择决定分组粒度partitionBy(numbers, n n % 3)把所有元素按模 3 的余数分为 3 组余数0、1、2对应的键分别为0、1、2注意1 % 3与4 % 3同为1因此1和4被归入同一组而partitionBy(numbers, n n)以元素自身为键得到的是去重分组效果——每个不同值独立成组等价于同时记录频率。这说明Map以键去重的特性天然保证了同键合并。键可以是任意值而非仅字符串与以普通对象为累加器的groupBy见 group-array-elements.md它用acc[key] (acc[key] || []).concat(arr[i])配合对象属性访问不同Map允许数字、对象、布尔值等任意类型作为键不会发生隐式字符串化。例如上面用数字0、1、2作为键用对象实现时这些键会被强制转换为0、1、2字符串属性语义上虽有偏差但多数场景无碍Map则更严谨。展开运算符与迭代器的组合[...map.values()]先取到Map中所有分区数组构成的迭代器再展开为普通数组。由于插入顺序即Map的迭代顺序分组的输出顺序与元素首次出现的分组顺序一致结果可预期、可复现。从调用链看partitionBy的判定函数fn(val, i, arr)同样接收元素、索引与原数组三个参数与partition完全一致两者都只做遍历与分组不修改原数组且fn的返回值都会被当作Map键或布尔判据使用语义上要求调用方自行保证键的一致性如避免NaN作为键——NaN在Map中可正常用作键但NaN ! NaN的语义差异不适用于键查找Map采用 SameValueZero 算法处理。与同族方案的关系bifurcate、groupBy 与 chunk在 30 seconds of code 的 JavaScript 集合中把数组拆分成多组并非孤立的单一片段而是围绕reduce展开的一组可互相参照的兄弟方案片段分组依据输出容器适用场景partition本文函数返回值的真值性固定双数组[[], []]二分类满足/不满足条件bifurcate/bifurcateBy预知布尔数组 / 函数固定双数组已知分组结果或需函数判定时的二分类partitionBy本文函数返回值任意键Map再展开为数组多分类、按任意键动态分组groupBy函数或属性名普通对象按字段或函数分组为对象chunk/chunkify固定块大小等长/变长子数组按长度分块而非按条件分组从仓库结构看这些片段被组织在 content/collections/js/ 下多个集合中例如array.yaml、array-methods.yaml与functional-programming.yaml等集合均围绕数组操作与函数式技巧展开redirects.yaml 中还可看到/js/s/partition-by、/js/s/partition、/js/s/partition-array-in-two等旧路径均以 301 状态重定向到/js/s/partition-array说明本文所述实现正是该仓库对分区这一主题的规范化入口。若需按固定大小切分而非按条件分组可进一步参考 split-array-into-chunks.md 中基于Math.ceil()、Array.from()与Array.prototype.slice()的分块写法。实践要点与注意事项判定函数的调用频次fn会在每次迭代中被调用一次若fn计算代价高昂如复杂对象属性计算可先在外部预计算结果或用Map缓存键值避免重复计算。空数组行为partition([], fn)返回[[], []]partitionBy([], fn)返回[]两者的空输入行为都是自然的零分区结果无需额外判空。键的稳定性多分区模式下如果fn对不同元素返回不一致的键如同一个逻辑分组却返回不同对象实例会意外产生多个分区应优先让fn返回原始值或规范化后的值如字符串、数字以确保分组语义正确。与filter的对比当只需要保留满足条件的元素时filter更直接但当需要同时保留两个分组做后续对比、统计或渲染时partition一次遍历即可同时得到两组避免对数组做两次过滤。兼容性两段代码仅依赖Array.prototype.reduce、Map与展开运算符均为现代 JavaScript 标准能力可直接运行于浏览器与 Node.js 环境reduce的四个回调参数累加器、当前值、当前索引、原数组在旧环境中的 polyfill 也保持一致。小结数组分区本质上是带分组语义的一次遍历双分区借助[[], []]二维累加器与三元索引映射把reduce的回调返回值翻译成数组下标多分区则升级为Map累加器用键管理任意数量的分组最后以Map.prototype.values()与展开运算符收束结果。掌握这两个模式后无论是用户按活跃状态分桶、数据按余数分簇还是任意字段的动态分组都可以用统一且可读的方式实现。如需进一步了解判定函数中真值性语义的边界情况可查阅 truthy-falsy-values.md想探索按属性分组为对象的变体可对照 group-array-elements.md。赞分享教程文档【免费下载链接】30-seconds-of-codeCoding articles to level up your development skills项目地址https://gitcode.com/gh_mirrors/30/30-seconds-of-code点击查看免费下载相关推荐Pillow ImageCMS输出模式越界Exploitarium Python图像库OOB写PoC完整拆解Pillow ImageCMS输出模式越界Exploitarium Python图像库OOB写PoC完整拆解 Exploitarium 是一个开源的漏洞 Po教程文档30-seconds-of-code 实战指南掌握 JavaScript 四大数组方法 map、filter、reduce 与 find30 seconds of code 实战指南掌握 JavaScript 四大数组方法 map、filter、reduce 与 find 本文以 30 sec教程文档30-seconds-of-code 实战用 reduce 将 JavaScript 数组按条件二分Bifurcate Array30 seconds of code 实战用 reduce 将 JavaScript 数组按条件二分Bifurcate Array 将数组一分为二bif教程文档上一篇Radicale配置详解如何设置安全认证和权限管理下一篇AI ShortChatGPT Shortcut提示词库入门指南30 秒快速上手、个人收藏与离线部署创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考